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

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

我知道我可以使用HTTP POST上传文件。 我不熟悉web-sockets,但据我所知,二进制数据也可以这样发送,因为websockets是双向的,我可以获得上传的进度。

我并不担心旧版浏览器,所以iframe和flash解决scheme并不是很吸引人,除非在这条路线上有明显的优势。

我也很好奇最好的服务器端技术。 他们的优势是使用像Django一样的wsgi服务器吗? 或者也许非阻塞I / O技术,如Node.js? 我不问,如果Web框架X比Web框架好,或者服务器X比服务器Y好。 但是,简单地说,理想的技术应该有什么设施上传到客户端。

更新似乎服务器端并不影响客户端上提供的技术/ API,以方便上传。

编辑 (2017-10-17):截至目前,还有使用Fetch API的选项。 它提供了与更现代的基于承诺的API背后的XMLHttpRequest基本相同的function。 浏览器有一个polyfill ,它本身不支持window.fetch() (现在主要是Internet Explorer和较早的Safari版本)。

XMLHttpRequest与Web套接字VS别的东西

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

虽然networking套接字在某些情况下是不错的,但它是一种不同的协议,增加了很多复杂性 – 如果您需要来自服务器的实时响应,它们只值得使用。 正如你所提到的,像Flash这样的其他方法只是丑陋的黑客。

发送二进制数据

通常情况下,你将不能直接访问文件。 所以你的页面上会有一个<input type="file">表单字段,然后等待用户select一个文件。 然后选项是:

  • 仅发送文件内容: request.send(input.files[0]) 。 请求主体将是文件的内容,没有别的,不会执行编码,也不会传输文件名称等元数据。 浏览器兼容性 :Chrome 7,Firefox 3.6,Opera 12,IE 10。
  • 发送整个表单的数据 : request.send(new FormData(input.form)) 。 在这里,表单内容将被编码为multipart/form-data ,这意味着您可以发送多个表单字段,元数据如字段和文件名也将被传输。 您也可以在发送之前修改FormData对象 。 取决于服务器端框架,处理这个请求可能比原始数据更简单,通常有许多助手可以使用。 浏览器兼容性 :Chrome 6,Firefox 4,Opera 12,IE 10。
  • 发送一个types数组 :以防万一你没有一个文件,但只是想发送一些即时生成的二进制数据。 这里没有额外的编码,所以就服务器端而言,这个工作就像发送文件内容一样。 浏览器兼容性 :Chrome 9,Firefox 9,Opera 11.60,IE 10。

显示上传进度

您可以监听XMLHttpRequest.upload上的progress事件 。 progress事件已经loaded total属性,可以确定你的请求有多远。 浏览器兼容性 :Chrome 7,Firefox 3.5,Opera 11.60,IE 10。

JavaScript库

当然现有的库封装了这里列出的function。 这些在其他答案中提到,在网上search肯定会变得更多。 我明确地不想在这里提出任何图书馆 – 哪一个如果你应该使用纯粹是一个偏好问题。

我的回答是相当晚,但这里是:


简短的回答:

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



什么是XMLHttpRequest?

XMLHttpRequest是由Microsoftdevise的,由Mozilla,Apple和Google采用的JavaScript对象。 现在正在W3C标准化 。 它提供了一种从URL中检索数据的简单方法,而无需进行整页刷新。 网页可以只更新页面的一部分,而不会中断用户正在做什么。 XMLHttpRequest在AJAX编程中被大量使用。

尽pipe它的名字,XMLHttpRequest可以用来检索任何types的数据,而不仅仅是XML ,它支持HTTP以外的协议 (包括文件和FTP )。

XMLHttpRequest对象已经在Html5规范中得到了改观。 特别是XMLHttpRequest Level 2 。


优点:

  • 处理字节stream,例如FileBlobFormData对象,用于上传和下载
  • 上传和下载期间的进度事件
  • 跨源请求
  • 允许匿名请求 – 这不是发送HTTP Referer
  • 为请求设置超时的能力
  • 上传正在后台进行
  • 用户所在页面保持不变
  • 不需要对服务器端任何改变 ,所以现有的服务器端逻辑应该保持不变,这使得这种技术更容易适应。

Html5进展事件:

根据Html5 Progress Events规范 ,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. Mimetypes
  4. 完成百分比的进度条
  5. 上传速度或上传带宽
  6. 剩余的大致时间
  7. 迄今为止上传的字节数
  8. 来自服务器端的响应

使用XMLHttpRequest演示file upload

例如,请查看“ 使用Html5进度file upload文件 ”。 所有需要的JavaScript代码都在页面中,但不包含CSS。 出于安全原因,文件types仅限于jpg,png,gif和txt。 最大文件大小是2MB。


XMLHttpRequest浏览器兼容性:

XMLHttpRequest浏览器兼容性


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文件POSTfunction很好的覆盖。

我个人喜欢blueimp jQueryfile upload插件( https://blueimp.github.io/jQuery-File-Upload/

file upload小部件,具有多个文件select,拖放支持,进度条,validation和预览图像,jQuery的audio和video。 支持跨域,分块和可恢复的file upload和客户端图像大小调整。 适用于任何支持标准HTML表单file upload的服务器端平台(PHP,Python,Ruby on Rails,Java,Node.js,Go等)。

演示:

  • 基本
  • 基本Plus
  • 基本Plus UI
  • AngularJS

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

文件可以通过AJAX上传。

使用jQuery表单插件 。 它完成将文件绑定到表单并将其序列化的所有肮脏工作。 它也能够显示上传进度。

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

演示