今天在使用koa下载文件的时候,一直抱错'invalid charactor',关键是明明测试都没得问题的,郁闷了老半天
this.set({"Content-disposition": `attachment; filename=test.xlsx`});
this.set({'Content-type': 'application/vnd.ms-excel'});
this.body = buffer;
后来返现测试上用的是test.xlsx,而生产上是动态的文件名,有些时候会是中文,所以基本上肯定了是header中编码的问题。
content-disposition
content-disposition是mime协议的扩展,而mime协议指示mime用户代理如何显示附加的文件,content-disposition其实可以控制用户请求所得到内容为一个文件时为其提供一个文件名字,文件可以是直接在浏览器上显示或文件下载。
注:disposition-type 文件的下载方式, inline直接在浏览器中打开,attachment以附件形式
content-disposition中的编码
http header中有content-type来指定body的编码,但是header中却没有,如果header中携带里信息却没有编码(默认是ACSII码),那浏览器是无法识别header中信息的,可能就会导致某些问题。
2010年 RFC 5987 发布,正式规定了 HTTP Header 中多语言编码的处理方式,应当采用类似 MIME 扩展的 parameter*=charset'lang'value 的格式,但是其中 value 应根据 RFC 3986 Section 2.1 使用百分号进行编码,并且规定浏览器至少应该支持 ASCII 和 UTF-8 。
例如
Content-Disposition: attachment;filename="encoded_text";filename*=utf-8''encoded_text
对于ascii码采用最简单的filename='name.text'无需编码,对于可能含有非acss码(通常是UTF-8)建议使用上面的形式
针对上面的问题我自己的代码如下
this.set({"Content-disposition": `attachment; filename*=UTF-8''${urlencode(name)}.xlsx`});
this.set({'Content-type': 'application/vnd.ms-excel'});
this.body = buffer;