如何使用 jQuery 异步上传文件?

IT技术 javascript jquery ajax asynchronous xmlhttprequest
2020-12-16 22:07:24

我想用 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"/>

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

6个回答

使用HTML5,您可以使用 Ajax 和 jQuery 进行文件上传。不仅如此,您还可以进行文件验证(名称、大小和 MIME 类型)或使用 HTML5 进度标记(或 div)处理进度事件。最近我不得不制作一个文件上传器,但我不想使用Flash、Iframes 或插件,经过一些研究,我想出了解决方案。

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 组件并非在所有浏览器中都可用。

这是FORMDATA谁在这里做所有的魔法。请务必查看这些文档——它涵盖了您关于多个文件和字段的所有问题。
2021-02-07 22:07:24
我有文件部分工作......但是你可以在其中包含文本字段吗?这似乎与var formData = new FormData($('form')[0]);serialize()?
2021-02-10 22:07:24
这应该适用于 Internet Explorer,但仅适用于版本 10。(caniuse.com/xhr2
2021-03-03 22:07:24
嗨,我很欣赏 PHP 是您选择的语言……但我想知道您是否知道这是否也适用于 ASP.NET MVC?我是一名 .NET 开发人员,我试图利用您的简单示例来上传一些 AJAX 文件,但服务器端我没有得到我通过 AJAX 发布的文件。我正在使用最新的 Chrome。
2021-03-03 22:07:24
然后我可以在upload.php 中使用$_FILES 吗?
2021-03-04 22:07:24

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

理解“新”HTML5 fileAPI的重要一点直到 IE 10 才支持如果您瞄准的特定市场对旧版 Windows 的倾向高于平均水平,您可能无法访问它。

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

截止本次编辑,现在是 2019 年,距我最初的回答将近 11 年。IE9 及更低版本在全球范围内的使用率在 1% 左右,但仍有较高使用率的集群。

从中得出的重要结论(无论功能如何)是,检查您的用户使用的浏览器如果你不这样做,你会学到一个快速而痛苦的教训,为什么“为我工作”在交付给客户的可交付成果方面不够好。caniuse是一个有用的工具,但请注意他们从哪里获得人口统计数据。他们可能与你的不一致。这永远不会比企业环境更真实。

我 2008 年的回答如下。


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

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

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

或者使用 Java/Flash 解决方案。他们可以更灵活地处理自己的帖子......

作为记录,如果浏览器支持文件 API,现在可以进行纯 AJAX 文件上传 - developer.mozilla.org/en/using_files_from_web_applications
2021-02-06 22:07:24
@BrettCaswell 我并不是说 AJAX/XHR 是不可能的,只是不可能在旧的 - 但永远存在 - 版本的 IE 上发布带有它们的文件。这曾经是,现在仍然是完全正确的。
2021-02-11 22:07:24
这是一个相当古老的答案,但它有点误导.. IE 早在 IE7 时就支持 XHR,早在 IE5 时就通过 ActiveX 支持它。w3schools.com/ajax/ajax_xmlhttprequest_create.asp这样做的实际方法当然是针对 Flash (shockwave) 组件,或者推出 Flash/ActiveX (Silverlight) 控件。如果您可以通过 javascript 发起请求并处理响应,那么它就是 ajax .. 不过,话虽如此,ajax 是 xhr 的同义词,但它本身并不描述传递/交换有效负载的下划线机制/组件。
2021-02-14 22:07:24

为此,我建议使用Fine Uploader插件。您的JavaScript代码将是:

$(document).ready(function() {
  $("#uploadbutton").jsupload({
    action: "addFile.do",
    onComplete: function(response){
      alert( "server response: " + response);
    }
  });
});
如果有人试图走这条路,FineUploader 已于 2018 年停产。github.com/FineUploader/fine-uploader/issues/2073
2021-02-12 22:07:24
“此插件在 GNU GPL 2 或更高版本和 GNU LGPL 2 或更高版本下开源。” 因此,只要您不分发副本或修改版本,您就不必打开您的项目。
2021-02-28 22:07:24

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


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

小注:在最新版本的 chrome 和 firefox 中是可能的,stackoverflow.com/questions/4856917/...
2021-02-17 22:07:24

为未来的读者总结。

异步文件上传

使用 HTML5

您可以将文件上传与jQuery使用$.ajax()方法,如果FORMDATA文件API的支持(包括HTML5功能)。

您也可以在没有 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(无文件 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 表单插件jQuery 文件上传)包括从 HTML5 到不同回退的整个堆栈和一些有用的功能,以简化流程。根据您的需要和要求,您可能需要考虑裸实现或此插件中的任何一个。