天天看点

[多浏览器兼容]下载文件名乱码

下载文件时,若文件名含有Unicode字符,下载的文件名可能是乱码(在IE上是乱码,FF和Chrome正常),在IE上这个问题还比较常见,尤其是老版本IE(IE6/7/8)。这个问题得在Server端解决。

[多浏览器兼容]下载文件名乱码

分析

文件名是怎么从Server端传到浏览器的?文件名是通过Server端回复的HTTP头的Content-Disposition传过来的,比如Content-Disposition:attachment; filename=genome.jpeg就告诉浏览器,Server将要发给你的是文件,文件名为genome.jpeg。而RFC2138规定,Content-Disposition中的filename参数内容,只能是ASCII编码。

那Unicode文件名是怎么从server端传到浏览器的呢?各个浏览器的处理方法就不一样了。假设在Dropbox中有一个“测试文件.txt”,用不同的浏览器下载这个文件:

  • Chrome45的content-disposition内容为

    attachment;filename="%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt";filename*=UTF-8''%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt

  • IE11的content-disposition内容为

    attachment;filename=%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt

  • FF的content-disposition内容为

    attachment; filename="测试文件.txt";filename*=UTF- 8''%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt

结论

对于Unicode文件名,各个浏览器能接受的content-disposition内容不一样。但是,经实测,下面这种格式,对于IE9,Chrome,FF,都是可行的。注意content-disposition内容有三段组成。

    attachment; filename="%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt";filename*=UTF-8''%E6%B5%8B%E8%AF%95%E6%96%87%E4%BB%B6.txt

所以,对于主流浏览器,可以将文件名做URL-Encode后,送入如下字符串,作为content-position的值。(具体见这个python的Commit)

    'attachment; filename="{0}";filename*=UTF-8\'\'{1}'

对于Android浏览器,还要加其它的代码支持,详见[1],其中给出了详细的方案:

  • 对于IE7 & IE8
contentDisposition = "attachment;filename=" + Uri.EscapeDataString(fileName);
           
  • 对于非Android浏览器
contentDisposition = "attachment;filename=\"" + fileName + "\"; filename*=UTF-8''" +Uri.EscapeDataString(fileName);
           

最后,记住,这个多浏览器兼容的问题,必须在Server端解决。

Ref:

[1] http://stackoverflow.com/questions/93551/how-to-encode-the-filename-parameter-of-content-disposition-header-in-http