我有个要求,我需要从网站上下载一份PDF。PDF需要在代码中生成,我认为这将是freemarker和像iText这样的PDF生成框架的组合。还有更好的办法吗?
然而,我的主要问题是如何允许用户通过Spring控制器下载文件?
我有个要求,我需要从网站上下载一份PDF。PDF需要在代码中生成,我认为这将是freemarker和像iText这样的PDF生成框架的组合。还有更好的办法吗?
然而,我的主要问题是如何允许用户通过Spring控制器下载文件?
当前回答
您应该能够直接在响应上写入文件。类似的
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"somefile.pdf\"");
然后在response.getOutputStream()上将该文件写入二进制流。记得在最后执行response.flush(),这样就可以了。
其他回答
我能够通过使用Spring的ResourceHttpMessageConverter中的内置支持来进行流处理。如果可以确定mime类型,这将设置内容长度和内容类型
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
@ResponseBody
public FileSystemResource getFile(@PathVariable("file_name") String fileName) {
return new FileSystemResource(myService.getFileFor(fileName));
}
您应该能够直接在响应上写入文件。类似的
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=\"somefile.pdf\"");
然后在response.getOutputStream()上将该文件写入二进制流。记得在最后执行response.flush(),这样就可以了。
如果这对谁有帮助的话。你可以按照Infeligo给出的答案去做,但只需要在强制下载的代码中添加额外的内容即可。
response.setContentType("application/force-download");
如果你:
不想在发送到响应之前将整个文件加载到字节[]中; 希望/需要通过InputStream发送/下载; 想要有Mime类型和文件名发送的完全控制; 让其他@ControllerAdvice为你(或不)拾取异常。
下面的代码是你需要的:
@RequestMapping(value = "/stuff/{stuffId}", method = RequestMethod.GET)
public ResponseEntity<FileSystemResource> downloadStuff(@PathVariable int stuffId)
throws IOException {
String fullPath = stuffService.figureOutFileNameFor(stuffId);
File file = new File(fullPath);
long fileLength = file.length(); // this is ok, but see note below
HttpHeaders respHeaders = new HttpHeaders();
respHeaders.setContentType("application/pdf");
respHeaders.setContentLength(fileLength);
respHeaders.setContentDispositionFormData("attachment", "fileNameIwant.pdf");
return new ResponseEntity<FileSystemResource>(
new FileSystemResource(file), respHeaders, HttpStatus.OK
);
}
More on setContentLength(): First of all, the content-length header is optional per the HTTP 1.1 RFC. Still, if you can provide a value, it is better. To obtain such value, know that File#length() should be good enough in the general case, so it is a safe default choice. In very specific scenarios, though, it can be slow, in which case you should have it stored previously (e.g. in the DB), not calculated on the fly. Slow scenarios include: if the file is very large, specially if it is on a remote system or something more elaborated like that - a database, maybe.
InputStreamResource
如果你的资源不是一个文件,例如你从DB中获取数据,你应该使用InputStreamResource。例子:
InputStreamResource isr = new InputStreamResource(...);
return new ResponseEntity<InputStreamResource>(isr, respHeaders, HttpStatus.OK);
我必须加上这个才能下载任何文件
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename="+"file.txt");
所有的代码:
@Controller
public class FileController {
@RequestMapping(value = "/file", method =RequestMethod.GET)
@ResponseBody
public FileSystemResource getFile(HttpServletResponse response) {
final File file = new File("file.txt");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename="+"file.txt");
return new FileSystemResource(file);
}
}