在现代浏览器中上传文件的最佳方式是什么?
我想上传(单个)文件到服务器,并显示上传的进度。
我知道我可以使用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,例如File , Blob和FormData对象,用于上传和下载
- 上传和下载期间的进度事件
- 跨源请求
- 允许匿名请求 – 这不是发送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
使用上述信息,向用户提供“剩余时间”信息是相当容易的。
通知用户:
有关可供用户使用的文件的信息:
- 文件名
- 文件大小
- Mimetypes
- 完成百分比的进度条
- 上传速度或上传带宽
- 剩余的大致时间
- 迄今为止上传的字节数
- 来自服务器端的响应
使用XMLHttpRequest演示file upload
例如,请查看“ 使用Html5进度file upload文件 ”。 所有需要的JavaScript代码都在页面中,但不包含CSS。 出于安全原因,文件types仅限于jpg,png,gif和txt。 最大文件大小是2MB。
XMLHttpRequest浏览器兼容性:
Javascript的文件API可能是现代浏览器中最好的方法:
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表单插件 。 它完成将文件绑定到表单并将其序列化的所有肮脏工作。 它也能够显示上传进度。
服务器堆栈与它没有太大的关系。
演示