在此之前,此功能的实现是用户点击一个url,服务器返回一个二进制流,浏览器下载后是一个PDF文件,客户可以进行浏览。
此次收到了合作方的新要求,能够在微信中点击url ,直接预览PDF中的内容。
第一版:做了非常简单的更改,在response中Set了打开方式 :
response.addHeader("Content-disposition", "attachment; filename="+ new String(polno.getBytes("utf-8"), "ISO8859-1")+"."+suffix);
//原打开方式,Content-disposition:attachment
response.addHeader("Content-disposition", "inline; filename="+ new String(polno.getBytes("utf-8"), "ISO8859-1")+"."+suffix);
//更改后打开方式,Content-disposition:inline
response中header的Content-disposition属性由attachment改为inline , 效果在测试环境表现为连接跳转为直接打开的pdf文件预览,在微信中也可以直接进入预览界面。
但当日上线中,发现存在问题,在苹果设备中(IOS13),微信浏览器中打开时表现为乱码:
在这种情况下紧急进行排错,首先使用Soup-UI模拟浏览器进行对连接的访问,观察返回头信息:
- 在测试环境,没有返回文件格式;
- 在生产环境,返回文件格式为“text”;
由此可以猜想,是该文件头导致流被解析的时候错误解析为文本,导致乱码。测试环境无防火墙限制,返回是完整二进制流,文件命名后能更新为pdf文件,而生产环境因为防火墙限制,可能在转发时默认设了值。
第二版:设置文件返回格式:
response.setContentType("application/octet-stream");
//原本设置,文件类型为二进制流;
response.setContentType("application/pdf");
//更改为返回文件声明为pdf
效果是再次使用soupUI访问,测试环境可以捕捉到头中有了文件类型,然而生产环境这个代码没有起到任何作用 !
再次分析原因,在测试环境、生产环境服务器上分别执行locale 命令,
生产:
测试:
分析可能是编码格式导致的?
第三版:
response.setContentType("application/pdf;charset=utf-8");
//更改为返回文件声明为pdf,且声明编码格式为UTF-8,与服务器同步
问题得到完美解决。