我想用jQuery异步上传文件。

$(文档).ready(函数(){$(“#uploadbutton”).click(函数(){var filename=$(“#file”).val();$.ajax美元({类型:“POST”,url:“addFile.do”,enctype:'多部分/表单数据',数据:{文件:文件名},成功:函数(){alert(“上传的数据:”);}});});});<script src=“https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.0/jquery.min.js“></script><span>文件</span><input type=“file”id=“file”name=“file”size=“10”/><input id=“uploadbutton”type=“button”value=“Upload”/>

我只得到文件名,而不是上传文件。我可以做什么来解决这个问题?


当前回答

jQueryUploadify是我以前用来上传文件的另一个好插件。JavaScript代码如下所示:code。但是,新版本在Internet Explorer中不起作用。

$('#file_upload').uploadify({
    'swf': '/public/js/uploadify.swf',
    'uploader': '/Upload.ashx?formGuid=' + $('#formGuid').val(),
    'cancelImg': '/public/images/uploadify-cancel.png',
    'multi': true,
    'onQueueComplete': function (queueData) {
        // ...
    },
    'onUploadStart': function (file) {
        // ...
    }
});

我做了大量的搜索,我找到了另一种不用任何插件、只使用ajax上传文件的解决方案。解决方案如下:

$(document).ready(function () {
    $('#btn_Upload').live('click', AjaxFileUpload);
});

function AjaxFileUpload() {
    var fileInput = document.getElementById("#Uploader");
    var file = fileInput.files[0];
    var fd = new FormData();
    fd.append("files", file);
    var xhr = new XMLHttpRequest();
    xhr.open("POST", 'Uploader.ashx');
    xhr.onreadystatechange = function () {
        if (xhr.readyState == 4) {
             alert('success');
        }
        else if (uploadResult == 'success')
            alert('error');
    };
    xhr.send(fd);
}

其他回答

注意:此答案已过时,现在可以使用XHR上载文件。


不能使用XMLHttpRequest(Ajax)上载文件。可以使用iframe或Flash模拟效果。优秀的jQuery表单插件,通过iframe发布文件以获得效果。

2019年更新:这仍然取决于您的人口统计使用的浏览器。

使用“新”HTML5文件API需要了解的一件重要事情是,直到IE 10才支持它。如果你所瞄准的特定市场对旧版本Windows的倾向高于平均水平,你可能无法访问它。

截至2017年,约5%的浏览器是IE 6、7、8或9之一。如果你进入一家大公司(例如,这是一个B2B工具或你提供的培训工具),这个数字可能会飙升。2016年,我与一家在60%以上的机器上使用IE8的公司打过交道。

截至本期编辑时,已是2019年,距离我最初的答案已经过去了11年。IE9和IE9的全球使用率在1%左右,但仍有使用率较高的集群。

无论有什么功能,重要的一点是检查用户使用的浏览器。如果你不这样做,你会很快学到一个痛苦的教训,为什么“为我工作”在交付给客户时不够好。犬科动物是一种有用的工具,但请注意它们的人口统计数据来源。它们可能与您的不一致。这比企业环境更真实。

我2008年的回答如下。


然而,有一些可行的非JS文件上传方法。您可以在页面上创建一个iframe(用CSS隐藏),然后将表单定位到该iframe。主页不需要移动。

这是一个“真实”的帖子,所以它不完全是交互式的。如果你需要状态,你需要服务器端的东西来处理。这取决于您的服务器。ASP.NET有更好的机制。PHP失败了,但您可以使用Perl或Apache修改来解决它。

如果您需要多个文件上传,最好一次上传一个文件(以克服最大文件上传限制)。将第一个表单发布到iframe,使用上面的方法监视其进度,完成后,将第二个表单发布给iframe等等。

或者使用Java/Flash解决方案。他们在处理自己的帖子时更加灵活。。。

如果使用承诺使用哪种ajax,并检查文件是否有效并保存在后端,那么您可以在用户浏览页面时在前面使用一些动画。

您甚至可以使用递归方法使其并行上传或堆叠

我已经在Rails环境中编写了这篇文章。如果您使用轻量级的jQuery表单插件,它只有大约五行JavaScript。

挑战在于如何让AJAX上传工作,因为标准的remote_form_for不理解多部分表单提交。它不会发送Rails通过AJAX请求返回的文件数据。

这就是jQuery表单插件发挥作用的地方。

下面是它的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上使用这个,它的效果就像一个冠军。

你可以很容易地用普通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);