javascript - 如何异步上传文件?

  显示原文与译文双语对照的内容

我想用jQuery异步上传一个文件。 这是我的HTML:


<span>File</span>
<input type="file" id="file" name="file" size="10"/>
<input id="uploadbutton" type="button" value="Upload"/>

这里是我的JavaScript代码:


$(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:");
 }
 });
 });
});

而不是上传的文件,我只得到文件名。 如何解决这个问题?

当前解决方案

我使用 jQuery表单插件来上传文件。

时间:

使用 HTML5,你可以使用Ajax和jQuery进行文件上传。 不仅如此,你还可以执行文件验证( 名称,大小和 MIME-type ) 或者使用HTML5进度标记( 或者一个 div ) 处理进度事件。 最近我不得不创建一个文件上传器,但是我不想使用 Flash 或者iframe或者插件,在一些研究之后我想到了解决方案。

HTML:


<form enctype="multipart/form-data">
 <input name="file" type="file"/>
 <input type="button" value="Upload"/>
</form>
<progress></progress>

首先,如果你愿意,可以进行一些验证。 例如在 file:的onChange事件中


$(':file').change(function(){
 var file = this.files[0];
 var name = file.name;
 var size = file.size;
 var type = file.type;
//Your validation
});

现在,Ajax通过点击按钮提交:


$(':button').click(function(){
 var formData = new FormData($('form')[0]);
 $.ajax({
 url: 'upload.php',//Server script to process data
 type: 'POST',
 xhr: function() {//Custom XMLHttpRequest
 var myXhr = $.ajaxSettings.xhr();
 if(myXhr.upload){//Check if upload property exists
 myXhr.upload.addEventListener('progress',progressHandlingFunction, false);//For handling the progress of the upload
 }
 return myXhr;
 },
//Ajax events
 beforeSend: beforeSendHandler,
 success: completeHandler,
 error: errorHandler,
//Form data
 data: formData,
//Options to tell jQuery not to process data or worry about content-type.
 cache: false,
 contentType: false,
 processData: false
 });
});

现在如果你想处理这个过程。


function progressHandlingFunction(e){
 if(e.lengthComputable){
 $('progress').attr({value:e.loaded,max:e.total});
 }
}

就像你所看到的,使用 HTML5 ( 还有一些研究) 文件上传不仅可以,而且非常容易。 尝试使用 Google Chrome,因为一些HTML5组件在每个浏览器中都不可用。

在jQuery上执行文件上传的ready-made插件有很多。

这样的上传攻击不是一个愉快的体验,所以人们喜欢使用ready-made解决方案。

下面是几点:

你可以从jquery站点的插件中搜索更多。

你几乎不能 Ajax文件上传如果你需要广泛的浏览器支持。

新文件api不支持在 IE 版本 10所以根据你拉你的数据和你的自然人口,你看着 5 -20%用户。 对于大多数理智的开发人员来说,这是一个unaffordable损失。

但是,如果在页面( 你可以用CSS隐藏) 上创建一个 iframe,则可以将窗体定位到该 iframe 。 主页不需要移动。

因为它是一个真正的帖子,所以它不是完全交互的,所以你需要从服务器上查看当前上传的进度。 根据你的服务器,这变化很大。 ASP.NET 具有更好的机制。 PHP plain失败,但你可以使用 Perl 或者Apache修改来绕过它。

如果你需要多个 file-uploads,最好每次都做一个文件( 克服最大文件上传限制) 。 将第一个窗体投递到 iframe,使用上面的方法监视它的进度,并在完成后将第二个窗体投递到 iframe,等等。

或者使用 java/Flash 解决方案。 他们在自己的文章中可以灵活得多。

我建议使用精细上传插件插件。 你的JavaScript代码是:


$(document).ready(function() {
 $("#uploadbutton").jsupload({
 action:"addFile.do",
 onComplete: function(response){
 alert("server response:" + response);
 }
 });

这个 AJAX文件上传jQuery插件上载文件 somehwere,并将响应传递给一个回调,没有其他的。

  • 它不依赖于特定的HTML,只需给它一个 <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');
 }
});

你不能使用 XMLHttpRequest ( Ajax ) 上传文件。 你可以使用iframe或者 Flash 模拟效果。 试swf( Flash ) 上传 SWFUpload

或者是优秀的jQuery表单插件,它通过iframe来发布你的文件。

我一直在使用下面的脚本来上传那些能正常工作的图片。

HTML


<input id="file" type="file" name="file"/>
<div id="response"></div>

Javascript


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);
});

说明

我使用响应 div 在上传完成后显示上传动画和响应。

最好的部分是当你使用这个脚本时,你可以发送额外的数据,比如&等。 我在脚本中提到过 extra-data

在PHP级别,这将作为普通文件上传工作。 extra-data可以作为 $_POST 数据检索。

这里你没有使用插件和内容。 你可以根据需要更改代码。 你不是在这里盲目编码。 这是任何jQuery文件上传的核心功能。 实际上是 Javascript 。

我已经在 Rails 环境中编写了它。 如果你使用的是轻量级的jQuery-form插件,它只有大约五行的JavaScript 。

挑战在于AJAX上传工作,因为标准的remote_form_for 不理解multi-part表单提交。 它不会发送 Rails 请求返回的文件数据。

这就是jQuery-form插件发挥作用的地方。

下面是 Rails 代码:


<% remote_form_for(:image_form, 
 :url => { :controller =>"blogs", :action => :create_asset }, 
 :html => { :method => :post, 
 :id => 'uploadForm', :multipart => true }) 
 do |f| %>
 Upload a file: <%= f.file_field :uploaded_data %>
<% end %>

下面是相关的JavaScript:


$('#uploadForm input').change(function(){
 $(this).parent().ajaxSubmit({
 beforeSubmit: function(a,f,o) {
 o.dataType = 'json';
 },
 complete: function(XMLHttpRequest, textStatus) {
//XMLHttpRequest.responseText will contain the URL of the uploaded image.
//Put it in an image element you create, or do with it what you will.
//For example, if you have an image elemtn with id"my_image", then
//$('#my_image').attr('src', XMLHttpRequest.responseText);
//Will set that image tag to display the uploaded image.
 },
 });
});

这是 Rails 控制器的动作,非常别致:


 @image = Image.new(params[:image_form])
 @image.save
 render :text => @image.public_filename

我在过去的几周里使用过 Bloggity,它像一个冠军。

...