我尝试使用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 viewer中显示时,它可以正常工作。请求/响应标头:
请求:
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配置中的东西?
如何强制下载正确的编码?
答案 0 :(得分:3)
来自评论:
比较文件大小,工作pdf为227403字节,另一个为303206字节
这表明数据为Base64 encoded。我不明白为什么会这样;大多数情况下,当服务器认为客户端无法处理二进制数据时(例如,当您执行AJAX请求时),就会产生这种效果。
[编辑] 安装Fiddler等代理服务器,可以查看服务器发送给浏览器的原始数据。尝试只创建一个小PDF,以使这更容易。
使用这些工具,您可以找出编码数据的人。
答案 1 :(得分:0)
如果您的pdf文件生成良好,我认为您应该尝试这种方式:
@RequestMapping(value = "clients/city")
@ResponseBody
private OutputStream getCity(HttpServletRequest request,HttpServletResponse response) throws IOException, JRException {
String path=request.getRealPath("resources/files");
createFileService.SpravkaCity(path);
// response.setContentType("text/plain");
// response.setHeader("Content-Disposition", "attachment; filename=reestr.xls");
File f=new File(path+"/city.pdf");
response.setContentType("application/pdf");
// response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Length", String.valueOf(f.length()));
response.setHeader("Content-Disposition", "inline; filename=city.pdf");
Path p = Paths.get(path+"/city.pdf");
response.getOutputStream().write(Files.readAllBytes(p));
return response.getOutputStream();
}
希望它会对你有所帮助。