【问题标题】:What is the best way to upload files in a modern browser在现代浏览器中上传文件的最佳方式是什么
【发布时间】:2015-06-21 22:34:53
【问题描述】:

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

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

我不担心旧版浏览器,所以 iframe 和 flash 解决方案不是很有吸引力,除非走这条路有显着优势。

我也很好奇最好的服务器端技术。使用像 Django 这样的 WSGI 服务器有优势吗?或者像 Node.js 这样的非阻塞 I/O 技术?我不是在问 web 框架 x 是否比 web 框架 y 好,或者服务器 x 是否比服务器 y 好。但只是为了方便在客户端上传,理想的技术应该具备的条件。

更新似乎服务器端与客户端上用于促进上传的技术/API 无关。

【问题讨论】:

  • 致投票结束我的问题的人,为什么它跑题了?我有一个特定的编程问题,可以回答...许多其他人都问过这个问题,但是随着浏览器技术的改进,这个问题的答案可能会改变。
  • vtortola 的回答是处理您的问题的最佳方式...使用 HTML5 File API。服务器端由您决定。无论哪种平台最适合您的整体需求。使用任何一个平台而不是另一个平台来上传文件不会有任何优势。 (我不是投票离题的人,只是觉得这更像是评论而不是答案)
  • 我删除了关于服务器端技术的部分。因为这可能基于一些意见,并且似乎不会影响客户端选项以促进上传。
  • 这是我过去某个时候做过的类似问题的答案:stackoverflow.com/questions/28014386/…
  • 在 Stack Overflow 上出现这样的问答应该没有什么问题。除非 Stack Overflow 没有尽可能地发挥作用。开发人员可以非常喜欢这个问题和答案,而且阅读起来非常方便。当有人提出这样的问题时,他们有什么选择?为什么 Stack 上没有这个问题的答案?看起来很奇怪。

标签: javascript django http file-upload websocket


【解决方案1】:

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

XMLHttpRequest 与 Web 套接字与其他东西

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

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

发送二进制数据

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

  • 仅发送文件内容:request.send(input.files[0])。请求正文将是文件的内容,仅此而已,不会执行任何编码,也不会传输文件名等元数据。 Browser compatibility:Chrome 7、Firefox 3.6、Opera 12、IE 10。
  • Sending the data of the entire formrequest.send(new FormData(input.form))。此处表单内容将被编码为multipart/form-data,这意味着您可以发送多个表单字段,并且还将传输字段和文件名等元数据。您也可以在发送之前modify the FormData object。根据服务器端框架,处理这个请求可能比原始数据更简单,通常有很多助手可以使用。 Browser compatibility:Chrome 6、Firefox 4、Opera 12、IE 10。
  • Sending a typed array:以防万一您没有文件,而只是想发送一些您即时生成的二进制数据。这里没有执行额外的编码,所以就服务器端而言,这就像发送文件内容一样。 Browser compatibility:Ch​​rome 9、Firefox 9、Opera 11.60、IE 10。

显示上传进度

您可以listen to progress events on XMLHttpRequest.uploadprogress events 具有 loadedtotal 属性,可以确定您的请求已完成多远。 Browser compatibility:Chrome 7、Firefox 3.5、Opera 11.60、IE 10。

JavaScript 库

当然,现有的库封装了此处概述的功能。这些在其他答案中都提到了,在网络上搜索肯定会出现更多。我明确不想在这里提出任何库 - 如果有的话,您应该使用其中的哪一个纯粹是一个偏好问题。

【讨论】:

  • 我应该提一下,您可以通过xhr.send( inpFile.files[0] ); 轻松发送二进制(或文本)文件,您也可以 .send() 整个表单,无需费心FormData 除非你需要动态的东西。
  • @dandavis:你说得对,我只是忘记了文件是 blob。我相应地改变了我的答案,但是它变得太长了。
【解决方案2】:

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


简答:

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



什么是 XMLHttpRequest?

XMLHttpRequest 是一个JavaScript 对象,由 Microsoft 设计并被 Mozilla、Apple 和 Google 采用。现在是standardized in the W3C。它提供了一种从 URL 检索数据的简单方法,而无需刷新整个页面。网页可以只更新页面的一部分,而不会中断用户正在做的事情。 XMLHttpRequest 在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 浏览器兼容性:


【讨论】:

    【解决方案3】:

    可能 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 功能。

    【讨论】:

      【解决方案4】:

      文件可以通过 AJAX 上传。

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

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

      Demo

      【讨论】:

        【解决方案5】:

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

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

        演示:

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

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-03-28
          • 2012-04-22
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多