Spring REST/Swagger/Postman - 正在下载的损坏/空白文件
我关注了 这篇 帖子的功能:客户端现在可以下载文件(即 csv、pdf 和 zip).
I followed this post for the functionality: client can download a file(ie, csv,pdf and zip) as of now.
但是我得到的是空白的 pdf,或者在尝试使用 zip 文件时,它会损坏.只有 CSV 可以正常工作.
我检查了标题,一切似乎都符合标准.我什至没有使用application/octet-stream",而是将application/pdf"用于 pdf,application/csv"用于 csv,application/zip"用于 zip,只是为了避免客户端出现任何问题.我正在使用 swagger 2.4 来测试我的 api.这是我的代码.
I have checked the headers, everything seems as per the standard. I am not even using "application/octet-stream" and using "application/pdf" for pdf, "application/csv" for csv and "application/zip" for zip just to avoid any issue with client. I am using swagger 2.4 to test my apis. Here is my code.
@CrossOrigin
@Controller
public class ReportRestController {
@Autowired
ReportService reportService;
@Value("${report.temp.directory}") // used for storing file in local
private String reportLocation;
@ApiImplicitParams({
@ApiImplicitParam(name = "Authorization", value = "Authorization", required = true, dataType = "string", paramType = "header"),
@ApiImplicitParam(name = "Auth-Provider", value = "Auth-Provider", required = true, dataType = "string", paramType = "header"),})
@RequestMapping(value = "/report/{type}/{format}", method = RequestMethod.POST)
public void getList(@RequestHeader(value = "UserId", required = false) Long userId,
@RequestHeader(value = "TeamId", required = false) Long teamId,
@RequestHeader(value = "CustomerId", required = true) Long customerId,
@PathVariable("type") String type, @PathVariable("format") String formate,
@RequestBody ReportRequestObj reportobj, HttpServletResponse response) {
String filename = reportService.getReport(customerId, userId, teamId, type, formate, reportobj);
Path pathfile = Paths.get(reportLocation, filename);
File file = pathfile.toFile();
if (file.exists()) {
String fileExtension = FilenameUtils.getExtension(filename);
if(CommonConstants.CSV.equals(fileExtension)){
response.setContentType("application/csv");
}else if(CommonConstants.PDF.equals(fileExtension)){
response.setContentType("application/pdf");
}else if(CommonConstants.ZIP.equals(fileExtension)){
response.setContentType("application/zip");
}
response.addHeader("Content-Disposition", "attachment; filename=" + filename);
response.setContentLength((int) file.length());
response.setHeader("Content-Transfer-Encoding", "binary");
try(FileInputStream fileInputStream = new FileInputStream(file)) {
IOUtils.copy(fileInputStream,response.getOutputStream());
response.getOutputStream().flush();
//response.flushBuffer();
} catch (IOException ex) {
log.error("Error while sending the file:{} for customerId:{} ,userId:{}",
file.getPath(), customerId, userId);
}
}
}
请让我知道我做错了什么或遗漏了什么?
Please let me know what I am doing wrong or missing ?
编辑 1:我附上了我得到的响应标头:
EDIT 1: I am attaching the response header I got:
{
"date": "Sun, 01 Jan 2017 19:11:13 GMT",
"x-content-type-options": "nosniff",
"access-control-max-age": "3600",
"content-disposition": "attachment; filename=localhost-blob-abcd.pdf",
"content-length": "172962",
"x-xss-protection": "1; mode=block",
"x-application-context": "report-server:8095",
"pragma": "no-cache",
"server": "Apache-Coyote/1.1",
"x-frame-options": "DENY",
"access-control-allow-methods": "POST, PUT, GET, OPTIONS, DELETE",
"content-type": "application/pdf;charset=UTF-8",
"access-control-allow-origin": "*",
"cache-control": "no-cache, no-store, max-age=0, must-revalidate, no-cache",
"access-control-allow-headers": "Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With, Auth-Provider, UserId, TeamId, Lang, CustomerId",
"expires": "0"
}
推荐答案
好的,这段代码对我有用:
Ok, this code works for me:
package com.example;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import javax.servlet.http.HttpServletResponse;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.core.io.InputStreamResource;
import org.springframework.http.CacheControl;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
@SpringBootApplication
public class DemoApplication {
public static void main(String[] args) {
SpringApplication.run(DemoApplication.class, args);
}
@Controller
public class DownloadController {
@RequestMapping("/download")
public ResponseEntity<InputStreamResource> download() throws FileNotFoundException {
final File file = new File("file.pdf");
return ResponseEntity.ok()
.contentLength(file.length())
.contentType(MediaType.APPLICATION_PDF)
.cacheControl(CacheControl.noCache())
.header("Content-Disposition", "attachment; filename=" + file.getName())
.body(new InputStreamResource(new FileInputStream(file)));
}
}
}
Spring Boot 没有什么特别之处,你可以在普通的 Spring MVC 中使用.
There is nothing specific to Spring Boot, you can use in with plain Spring MVC.
可能是这样的 Swagger 问题:通过 content-disposition 下载文件标头损坏文件,而不是服务器端文件.您是否尝试过使用其他工具测试此 API 调用?例如 curl 永远不会让我失望.
Maybe it is a Swagger issue like this: File download via content-disposition header corrupts file, not a server side one. Have you tried to test this API call with some other tool? For example curl never let me down.
相关文章