【发布时间】:2015-04-19 14:04:44
【问题描述】:
我试图了解使用 spring mvc servlet 下载 pdf 文件时的奇怪行为。
这是用于下载文件的控制器代码:
@RequestMapping(value = "/handler/{id}", method = RequestMethod.GET)
public HttpEntity<byte[]> report(@PathVariable("id") Long id,
HttpServletResponse response,
HttpServletRequest request) {
byte[] bytes = service.reportById(id);
return DownloadUtil.downloadFile(response, "application/pdf",
"Filename.pdf", bytes);
}
public static HttpEntity<byte[]> downloadFile(
final HttpServletResponse response,
final String contentType,
final String fileName,
final byte[] item){
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.valueOf(contentType));
header.set("Content-Disposition", "inline; filename=\"" + fileName +"\"");
header.set("Content-Transfer-Encoding", "application/octet-stream");
header.setContentLength(item.length);
return new HttpEntity<byte[]>(item, header);
}
当 pdf 在 chrome pdf 查看器中显示时,它可以工作。这里请求/响应标头:
请求:
GET /path/19649/download HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36
Referer: http://path/byDitta
Accept-Encoding: gzip, deflate, sdch
Accept-Language: it,en-US;q=0.8,en;q=0.6
Cookie: JSESSIONID=09CEA1438ACED879CDD96877BB536022; _ga=GA1.1.2013320496.1416898514
回应:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Disposition: inline; filename="file.pdf"
Content-Transfer-Encoding: application/octet-stream
Content-Type: application/pdf;charset=UTF-8
Content-Length: 296750
Date: Tue, 10 Mar 2015 09:39:05 GMT
当我保存在 pdf 查看器中显示的 pdf 时,我有这个请求/响应标头:
请求:
GET /path/19649/download HTTP/1.1
Host: localhost:8080
Connection: keep-alive
Referer: /path/19649/download
User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.76 Safari/537.36
Accept-Encoding: gzip, deflate, sdch
Accept-Language: it,en-US;q=0.8,en;q=0.6
Cookie: JSESSIONID=09CEA1438ACED879CDD96877BB536022; _ga=GA1.1.2013320496.1416898514
回应:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Content-Type-Options: nosniff
X-XSS-Protection: 1; mode=block
Cache-Control: no-cache, no-store, max-age=0, must-revalidate
Pragma: no-cache
Expires: 0
X-Frame-Options: DENY
Content-Disposition: inline; filename="file.pdf"
Content-Transfer-Encoding: application/octet-stream
Content-Type: application/pdf;charset=UTF-8
Content-Length: 296750
Date: Tue, 10 Mar 2015 09:40:29 GMT
我认为区别在于accept 请求标头。保存 pdf 请求中缺少它。
问题是,当这个文件被保存时,它有一个错误的编码,因此会被损坏。
奇怪的是我在另一个项目中使用〜相同的代码来做同样的事情并且它可以工作。所以我想,可能是 servlet 配置中的东西?
如何强制正确下载编码?
【问题讨论】:
-
你能告诉我们相应的响应头吗?特别是检查诸如“编码”和“字符集”之类的东西。我的猜测是文件是用gzip压缩的,需要解压。
-
谢谢@AaronDigulla 我已经为我的问题添加了详细信息。
-
@AaronDigulla 我尝试解压缩但没有成功。比较文件大小,工作pdf是227403字节,另一个是303206字节
-
@gipinani 你试过不同的浏览器了吗?您还可以将您的 Tomcat conf/server.xml 和 JVM 选项与其他服务器中的选项进行比较,以查找 WRT 编码提示的差异
-
application/pdf;charset=UTF-8没有意义,因为 PDF 是二进制格式。Content-Transfer-Encoding不是标准 HTTP 标头,application/octet-stream是 MIME 类型,而不是编码。也许 Chrome 对这些问题感到困惑。
标签: java spring google-chrome spring-mvc servlets