web开发中,如何让浏览器下载文件?

同学们,如果你看过我的书《深入浅出HTTPS:从原理的实战》 ,而且还觉得不错,希望能在豆瓣上做个评论


上个星期,一个对外的项目遇到浏览器下载附件错误的问题,简单的研究了下,涉及了二个问题:一个是通过编程如何让浏览器支持文件下载,第二个问题是如果附件是中文名称,如何避免文件出现乱码,这篇文章主要讲解文件下载的原理。

从本质上讲,为了支持文件下载,客户端(浏览器)和服务器支持特定的HTTP头即可,但不是所有的客户端(浏览器)都按照标准处理,比如说iPhone就无法通过浏览器下载文件。

rfc7231 中(HTTP/1.1 子协议 Semantics and Content)中已经说明 Content-Disposition 头并不是 HTTP 协议中的标准头,但 Content-Disposition 头在 HTTP 应用中有一定的应用场景,所以 rfc6266 详细描述了这个头部在 HTTP 中的使用标准,确切的说在 HTTP 应用中,这个头部称为 response header。

那么是否意味着 Content-Disposition 这个头部还有其他用途?是的,最早这个头在邮件应用中使用的比较多,属于 MIME 的一部分,Content-Disposition header(不是 response header)定义在 rfc2183 上,我在写《你真的知道网页上传文件背后的原理吗?》 》文章时,对于 MIME 中如何使用 Content-Disposition 有所涉及。

我参考 CodeIgniter PHP 框架,研究了文件下载的原理,实际上就是输出一些 HTTP 头部,如下图:

25-httpddownload-postman.png

大部分头部在常规的 HTTP 应用中(比如页面和接口)很常见,比如 Content-Length 表示附件的大小(在PHP中使用 strlen()算对吗?);Cache-Control和Expires控制缓存头,对于下载附件来说,就是强制获取最新内容;Content-Type表示附件的类型,不过如果你统一使用 application/octet-stream 也没有问题,浏览器照样能够下载;application/octet-stream 头部代表未知的应用(二进制文件)。

Content-Transfer-Encoding 这个头部是第一次看见,它和 Content-Type 头部有点类似,但主要用于传输。它在 multipart MIME 类型中用的比较多(如果一个实体是 multipart 类型,那么 Content-Transfer-Encoding 的值只能是 "7bit"、"8bit"、"binary"中的一个),对应到文件下载,这个值设置为 binary,表示允许非ASCII码进行传输。可以认为 application/octet-stream 等同于 Content-Transfer-Encoding:binary 。关于这个头部,理解的不是很好,可以参考 rfc2045(内容实在太多了)。

对于文件下载,最重要的HTTP头部就是 Content-Disposition,它用来表示内容如何在浏览器中显示:可以是内联(inline)呈现(对应的内容将作为页面的一部分呈现)或者附件下载(attachment)的形式。其中 filename 参数表示附件的名称,如果是中文,在不同的浏览器可能会出现乱码(这个我下一篇会简单说一说)。

本质上附件下载就是这么简单,但在 RFC 中没有清晰的看到实现附件下载的说明。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 本文包括:1、文件上传概述2、利用 Commons-fileupload 组件实现文件上传3、核心API——Dis...
    廖少少阅读 14,313评论 5 91
  • HTTP详细总结 一、前言 URI URI(统一资源标识符):我们使用HTTP协议,主要就用来访问互联网上的各种资...
    程序员小逗逼阅读 3,863评论 0 1
  • 网络 理论模型,分为七层物理层数据链路层传输层会话层表示层应用层 实际应用,分为四层链路层网络层传输层应用层 IP...
    FlyingLittlePG阅读 4,288评论 0 0
  • API定义规范 本规范设计基于如下使用场景: 请求频率不是非常高:如果产品的使用周期内请求频率非常高,建议使用双通...
    有涯逐无涯阅读 7,770评论 0 6
  • 文件下载,可以是post请求,也可以是get请求。 新建web项目,在WebRoot下建up目录存放上传的文件: ...
    神豪VS勇士赢阅读 7,317评论 0 0

友情链接更多精彩内容