在现代浏览器中上传文件的最佳方式是什么

What is the best way to upload files in a modern browser

我想上传一个(单个)文件到服务器并显示上传进度。

我知道我可以使用 HTTP POST 上传文件。我不熟悉网络套接字,但据我所知,二进制数据也可以通过这种方式发送,因为网络套接字是双向的,所以我可以获得上传进度。

我不担心较旧的浏览器,因此 iframe 和 flash 解决方案不是很吸引人,除非采用这种方式有显着优势。

我也很好奇最好的服务器端技术。他们使用像 Django 这样的 WSGI 服务器有优势吗?或者像 Node.js 这样的非阻塞 I/O 技术?我不是在问 Web 框架 x 是否比 Web 框架 y 好,或者服务器 x 是否比服务器 y 好。但简单来说,理想的技术应该具备什么,以便在客户端方便上传。

更新服务器端似乎与客户端上可用的 technologies/API 无关以方便上传。

可能 Javascript 的文件 API 是现代浏览器中的最佳方式:

http://robertnyman.com/2010/12/16/utilizing-the-html5-file-api-to-choose-upload-preview-and-see-progress-for-multiple-files/

http://www.sitepoint.com/html5-javascript-file-upload-progress-bar/

服务器端明智...我认为任何主要框架都很好地涵盖了 HTTP 文件 POST 功能。

编辑 (2017-10-17): 截至目前,对于不支持 [=10 的浏览器,还可以选择使用 Fetch API. It offers essentially the same capabilities as XMLHttpRequest behind a more modern promise-based API. There is a polyfill =] 本机(现在主要是 Internet Explorer 和较旧的 Safari 版本)。

XMLHttpRequest 与 Web 套接字与其他东西

显然XMLHttpRequest。它在现代浏览器中的功能是巨大的,几乎涵盖了所有场景。它将产生一个标准的 POST 或 PUT 请求,任何网络服务器和框架组合都可以处理。

虽然网络套接字在某些情况下很不错,但它是一种不同的协议,增加了很多复杂性 - 只有当您需要来自服务器的实时响应时才值得使用它们。正如您自己指出的那样,Flash 等其他方法只是丑陋的 hack。

发送二进制数据

通常,您不能直接访问文件。因此,您将在页面某处有一个 <input type="file"> 表单域,并等待用户选择一个文件。那么选项是:

  • 仅发送文件内容:request.send(input.files[0])。请求正文将是文件的内容,没有其他内容,不会执行任何编码,也不会传输文件名等元数据。 Browser compatibility: Chrome 7, Firefox 3.6, Opera 12, IE 10.
  • 正在发送整个表单的数据request.send(new FormData(input.form))。此处表单内容将被编码为 multipart/form-data,这意味着您可以发送多个表单字段,并且还会传输字段和文件名等元数据。您还可以在发送之前修改FormData 对象。根据服务器端框架的不同,处理此请求可能比原始数据更简单,通常可以使用许多帮助程序。 Browser compatibility: Chrome 6, Firefox 4, Opera 12, IE 10.
  • 发送类型化数组:以防万一您没有文件而只是想发送一些动态生成的二进制数据。这里没有执行额外的编码,所以就服务器端而言,这就像发送文件内容一样。 Browser compatibility: Chrome 9, Firefox 9, Opera 11.60, IE 10.

显示上传进度

您可以在 XMLHttpRequest.upload 收听 progress 事件。 progress 事件 具有 loadedtotal 属性,可以确定您的请求已经完成了多长时间。 Browser compatibility: Chrome 7, Firefox 3.5, Opera 11.60, IE 10.

JavaScript 图书馆

当然有一些现有的库包含这里概述的功能。这些在其他答案中都有提到,网上搜索肯定会更多。我明确不想在这里推荐任何库——如果有的话,你应该使用哪个库纯粹是一个偏好问题。

可以通过AJAX上传文件。

使用jQuery form plugin。它完成了将文件绑定到表单并将其序列化的所有脏活。它还能够显示上传进度。

服务器堆栈与它没有太大关系。

Demo

个人比较喜欢blueimpjQuery文件上传插件(https://blueimp.github.io/jQuery-File-Upload/)

File Upload widget with multiple file selection, drag&drop support, progress bars, validation and preview images, audio and video for jQuery. Supports cross-domain, chunked and resumable file uploads and client-side image resizing. Works with any server-side platform (PHP, Python, Ruby on Rails, Java, Node.js, Go etc.) that supports standard HTML form file uploads.

演示:

下载(GitHub): https://github.com/blueimp/jQuery-File-Upload

我的回答已经很晚了,但它是这样的:


简答:

XMLHttpRequest 是在现代浏览器中上传文件的最佳方式。



什么是XMLHttpRequest?

XMLHttpRequest 是一个JavaScript object that was designed by Microsoft and adopted by Mozilla, Apple, and Google. It's now being standardized in the W3C. It provides an easy way to retrieve data from a URL without having to do a full page refresh. A Web page can update just a part of the page without disrupting what the user is doing. XMLHttpRequest is used heavily in AJAX编程。

尽管名称如此,XMLHttpRequest 可用于检索任何类型的数据,而不仅仅是 XML,并且它支持除 HTTP(包括文件和ftp)。

XMLHttpRequest 对象在 Html5 规范中进行了整容。具体来说 XMLHttpRequest Level 2.


优点:

  • 处理字节流,例如 FileBlobFormData 对象,用于上传和正在下载
  • 上传和下载过程中的进度事件
  • 跨域 请求
  • 允许发出匿名请求 - 即不发送 HTTP Referer
  • 能够为请求设置超时
  • 正在后台上传
  • 用户所在的页面保持不变
  • 不需要对服务器端进行任何更改,因此现有的服务器端逻辑应该保持不变,这使得适应该技术变得更加容易。

Html5进度事件:

根据 Html5 Progress Events spec,Html5 进度事件提供以下信息:

total - Total bytes being transferred
loaded - Bytes uploaded thus far
lengthComputable - Specifies if the total size of the data/file being uploaded is known 

使用以上信息,可以很容易地向用户提供“剩余时间”信息。


让用户了解情况:

关于可以提供给用户的文件的信息:

  1. 文件名
  2. 文件大小
  3. Mime 类型
  4. 带有完成百分比的进度条
  5. 上传速度或上传带宽
  6. 大概剩余时间
  7. 到目前为止上传的字节数
  8. 服务器端的响应

使用 XMLHttpRequest 演示上传文件

请查看“Uploading files using Html5 with Progress indication demo”作为示例。所需的所有 JavaScript 代码都在页面中,但不包括 CSS。出于安全原因,文件类型仅限于 jpg、png、gif 和 txt。最大文件大小为 2MB。


XMLHttpRequest 浏览器兼容性: