我想用 jQuery 异步上传文件。
$(document).ready(function () {
$("#uploadbutton").click(function () {
var filename = $("#file").val();
$.ajax({
type: "POST",
url: "addFile.do",
enctype: 'multipart/form-data',
data: {
file: filename
},
success: function () {
alert("Data Uploaded: ");
}
});
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js"></script>
<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>
我只获取文件名,而不是上传文件。我该怎么做才能解决此问题?
使用HTML5,您可以使用 Ajax 和 jQuery 进行文件上传。不仅如此,您还可以执行文件验证(名称,大小和 MIME 类型)或使用 HTML5 进度标签(或 div)处理进度事件。最近,我不得不制作一个文件上传器,但是我不想使用Flash ,iframe 或插件,经过一番研究后,我提出了解决方案。
HTML:
<form enctype="multipart/form-data">
<input name="file" type="file" />
<input type="button" value="Upload" />
</form>
<progress></progress>
首先,您可以根据需要进行一些验证。例如,在文件的.on('change')
事件中:
$(':file').on('change', function () {
var file = this.files[0];
if (file.size > 1024) {
alert('max upload size is 1k');
}
// Also see .name, .type
});
现在,单击按钮即可提交$.ajax()
:
$(':button').on('click', function () {
$.ajax({
// Your server script to process the upload
url: 'upload.php',
type: 'POST',
// Form data
data: new FormData($('form')[0]),
// Tell jQuery not to process data or worry about content-type
// You *must* include these options!
cache: false,
contentType: false,
processData: false,
// Custom XMLHttpRequest
xhr: function () {
var myXhr = $.ajaxSettings.xhr();
if (myXhr.upload) {
// For handling the progress of the upload
myXhr.upload.addEventListener('progress', function (e) {
if (e.lengthComputable) {
$('progress').attr({
value: e.loaded,
max: e.total,
});
}
}, false);
}
return myXhr;
}
});
});
如您所见,借助 HTML5(和一些研究),文件上传不仅成为可能,而且超级容易。请尝试使用Google Chrome 浏览器,因为示例的某些 HTML5 组件并非在每种浏览器中都可用。
使用 “新” HTML5 file
API 时要了解的重要一点是, 直到 IE 10 才支持它。如果您要针对的特定市场对旧版本 Windows 的倾向高于平均水平,则可能无法使用它。
截至 2017 年,大约 5%的浏览器是 IE 6、7、8 或 9 之一。如果您进入一家大公司(例如,这是 B2B 工具,或者您要提供培训的内容),那么这个数字可能会飙升。 2016 年,我与一家在其 60%以上的计算机上使用 IE8 的公司打交道。
截至本次编辑的 2019 年,距离我最初的回答差不多 11 年了。 IE9 及更低版本在全球范围内均在 1%左右,但仍存在使用率更高的集群。
最重要的外卖从这个 - whatever 的特征 - 是, 请检查您的用户使用的浏览器 。如果不这样做,您将学到一个快速而痛苦的课程,以了解为什么 “为我工作” 在交付给客户的产品中不够好。 caniuse是一个有用的工具,但请注意他们从哪里获得人口统计信息。它们可能与您的不一致。这从未比企业环境更真实。
我在 2008 年的回答如下。
但是,有可行的非 JS 文件上传方法。您可以在页面上创建一个 iframe(使用 CSS 隐藏该 iframe),然后将表单定位为发布到该 iframe。主页不需要移动。
这是一个 “真实” 的帖子,因此并不完全是交互式的。如果您需要状态,则需要服务器端进行处理。具体取决于您的服务器。 ASP.NET具有更好的机制。 PHP 普通失败,但是您可以使用Perl或 Apache 修改来解决它。
如果您需要多个文件上传,则最好一次执行一个文件(以克服最大文件上传限制)。将第一个表单发布到 iframe 中,使用上述方法监视进度,完成后,将第二个表单发布到 iframe 中,依此类推。
我建议为此使用Fine Uploader插件。您的JavaScript
代码为:
$(document).ready(function() {
$("#uploadbutton").jsupload({
action: "addFile.do",
onComplete: function(response){
alert( "server response: " + response);
}
});
});
注意:此答案已过时,现在可以使用 XHR 上传文件。
您不能使用XMLHttpRequest (Ajax)上传文件。您可以使用 iframe 或 Flash 模拟效果。出色的jQuery 表单插件 ,可通过 iframe 发布文件以获得效果。
为将来的读者做准备。
如果支持FormData和File API (均具有 HTML5 功能),则可以使用$.ajax()
方法使用jQuery上传文件。
您也可以发送不带 FormData 的文件,但是必须以两种方式发送文件 API 来处理文件,以便可以使用XMLHttpRequest (Ajax)发送文件。
$.ajax({
url: 'file/destination.html',
type: 'POST',
data: new FormData($('#formWithFiles')[0]), // The form with the file inputs.
processData: false,
contentType: false // Using FormData, no need to process data.
}).done(function(){
console.log("Success: Files sent!");
}).fail(function(){
console.log("An error occurred, the files couldn't be sent!");
});
有关快速的纯 JavaScript( 无 jQuery )示例,请参见 “ 使用 FormData 对象发送文件 ”。
当不支持 HTML5(无File API )时,唯一的其他纯 JavaScript 解决方案(无Flash或任何其他浏览器插件)是隐藏的 iframe技术,该技术允许在不使用XMLHttpRequest对象的情况下模拟异步请求。
它包括通过输入文件将 iframe 设置为表单的目标。当用户提交请求并上传文件时,响应会显示在 iframe 中,而不是重新呈现主页。隐藏 iframe 可使整个过程对用户透明,并模拟异步请求。
如果做得正确,它实际上可以在任何浏览器上运行,但是在从 iframe 获取响应方面有一些警告。
在这种情况下,您可能更喜欢使用Bifröst 之类的包装器插件,该插件使用iframe 技术,但还提供了jQuery Ajax 传输,允许仅使用$.ajax()
方法发送文件 ,如下所示:
$.ajax({
url: 'file/destination.html',
type: 'POST',
// Set the transport to use (iframe means to use Bifröst)
// and the expected data type (json in this case).
dataType: 'iframe json',
fileInputs: $('input[type="file"]'), // The file inputs containing the files to send.
data: { msg: 'Some extra data you might need.'}
}).done(function(){
console.log("Success: Files sent!");
}).fail(function(){
console.log("An error occurred, the files couldn't be sent!");
});
Bifröst只是一个小的包装,它为 jQuery 的 ajax 方法添加了后备支持,但是许多上述插件,例如jQuery Form Plugin或jQuery File Upload,都包括从 HTML5 到不同后备的整个堆栈,以及一些简化该过程的有用功能。根据您的需求和要求,您可能需要考虑一个简单的实现或两个插件之一。
这个AJAX 文件上传 jQuery 插件以某种方式上传文件,并将响应传递给回调,仅此而已。
<input type="file">
- 少用 -
$('#one-specific-file').ajaxfileupload({
'action': '/upload.php'
});
- 或多达 -
$('input[type="file"]').ajaxfileupload({
'action': '/upload.php',
'params': {
'extra': 'info'
},
'onComplete': function(response) {
console.log('custom handler for file:');
alert(JSON.stringify(response));
},
'onStart': function() {
if(weWantedTo) return false; // cancels upload
},
'onCancel': function() {
console.log('no file selected');
}
});
我一直在使用下面的脚本上传图像,但效果很好。
<input id="file" type="file" name="file"/>
<div id="response"></div>
jQuery('document').ready(function(){
var input = document.getElementById("file");
var formdata = false;
if (window.FormData) {
formdata = new FormData();
}
input.addEventListener("change", function (evt) {
var i = 0, len = this.files.length, img, reader, file;
for ( ; i < len; i++ ) {
file = this.files[i];
if (!!file.type.match(/image.*/)) {
if ( window.FileReader ) {
reader = new FileReader();
reader.onloadend = function (e) {
//showUploadedItem(e.target.result, file.fileName);
};
reader.readAsDataURL(file);
}
if (formdata) {
formdata.append("image", file);
formdata.append("extra",'extra-data');
}
if (formdata) {
jQuery('div#response').html('<br /><img src="ajax-loader.gif"/>');
jQuery.ajax({
url: "upload.php",
type: "POST",
data: formdata,
processData: false,
contentType: false,
success: function (res) {
jQuery('div#response').html("Successfully uploaded");
}
});
}
}
else
{
alert('Not a vaild image!');
}
}
}, false);
});
我使用 response div
来显示上传动画和上传完成后的响应。
最好的部分是,使用此脚本时,您可以随文件发送额外的数据,例如 ids 等。我已经提到了脚本中的extra-data
。
在 PHP 级别,这将像正常文件上传一样工作。可以将多余数据作为$_POST
数据进行检索。
在这里,您没有使用插件和东西。您可以根据需要更改代码。您在这里不是盲目编码。这是任何 jQuery 文件上传的核心功能。其实是 Javascript。
您可以非常轻松地在原始 JavaScript 中完成此操作。这是我当前项目的摘录:
var xhr = new XMLHttpRequest();
xhr.upload.onprogress = function(e) {
var percent = (e.position/ e.totalSize);
// Render a pretty progress bar
};
xhr.onreadystatechange = function(e) {
if(this.readyState === 4) {
// Handle file upload complete
}
};
xhr.open('POST', '/upload', true);
xhr.setRequestHeader('X-FileName',file.name); // Pass the filename along
xhr.send(file);
您可以仅使用 jQuery .ajax()
上传。
HTML:
<form id="upload-form">
<div>
<label for="file">File:</label>
<input type="file" id="file" name="file" />
<progress class="progress" value="0" max="100"></progress>
</div>
<hr />
<input type="submit" value="Submit" />
</form>
的 CSS
.progress { display: none; }
Javascript:
$(document).ready(function(ev) {
$("#upload-form").on('submit', (function(ev) {
ev.preventDefault();
$.ajax({
xhr: function() {
var progress = $('.progress'),
xhr = $.ajaxSettings.xhr();
progress.show();
xhr.upload.onprogress = function(ev) {
if (ev.lengthComputable) {
var percentComplete = parseInt((ev.loaded / ev.total) * 100);
progress.val(percentComplete);
if (percentComplete === 100) {
progress.hide().val(0);
}
}
};
return xhr;
},
url: 'upload.php',
type: 'POST',
data: new FormData(this),
contentType: false,
cache: false,
processData: false,
success: function(data, status, xhr) {
// ...
},
error: function(xhr, status, error) {
// ...
}
});
}));
});
我过去做过的最简单,最可靠的方法是,仅将表单指向一个隐藏的 iFrame 标签 - 然后它将在 iframe 中提交而无需重新加载页面。
也就是说,如果您不想使用插件,JavaScript 或 HTML 以外的任何其他形式的 “魔术”。当然,您可以将其与 JavaScript 结合使用,或者您拥有什么...
<form target="iframe" action="" method="post" enctype="multipart/form-data">
<input name="file" type="file" />
<input type="button" value="Upload" />
</form>
<iframe name="iframe" id="iframe" style="display:none" ></iframe>
您还可以读取 iframe onLoad
的内容以获取服务器错误或成功响应,然后将其输出给用户。
Chrome,iFrame 和 onLoad
- 注意 - 如果您对上载 / 下载时如何设置 UI 阻止程序感兴趣,则只需要继续阅读
当前,Chrome 在用于传输文件时不会触发 iframe 的 onLoad 事件。 Firefox,IE 和 Edge 均会触发 onload 事件以进行文件传输。
我发现适用于 Chrome 的唯一解决方案是使用 Cookie。
要在开始上传 / 下载时基本上做到这一点:
为此使用 cookie 是很丑陋的,但是可以。
下载时,我制作了一个 jQuery 插件来处理 Chrome 的此问题,您可以在此处找到
https://github.com/ArtisticPhoenix/jQuery-Plugins/blob/master/iDownloader.js
相同的基本原理也适用于上传。
使用下载器(显然包括 JS)
$('body').iDownloader({
"onComplete" : function(){
$('#uiBlocker').css('display', 'none'); //hide ui blocker on complete
}
});
$('somebuttion').click( function(){
$('#uiBlocker').css('display', 'block'); //block the UI
$('body').iDownloader('download', 'htttp://example.com/location/of/download');
});
在服务器端,就在传输文件数据之前,创建 cookie
setcookie('iDownloader', true, time() + 30, "/");
插件将看到 cookie,然后触发onComplete
回调。