我有个要求,我需要从网站上下载一份PDF。PDF需要在代码中生成,我认为这将是freemarker和像iText这样的PDF生成框架的组合。还有更好的办法吗?
然而,我的主要问题是如何允许用户通过Spring控制器下载文件?
我有个要求,我需要从网站上下载一份PDF。PDF需要在代码中生成,我认为这将是freemarker和像iText这样的PDF生成框架的组合。还有更好的办法吗?
然而,我的主要问题是如何允许用户通过Spring控制器下载文件?
当前回答
如果这对谁有帮助的话。你可以按照Infeligo给出的答案去做,但只需要在强制下载的代码中添加额外的内容即可。
response.setContentType("application/force-download");
其他回答
@RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
public void getFile(
@PathVariable("file_name") String fileName,
HttpServletResponse response) {
try {
// get your file as InputStream
InputStream is = ...;
// copy it to response's OutputStream
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
} catch (IOException ex) {
log.info("Error writing file to output stream. Filename was '{}'", fileName, ex);
throw new RuntimeException("IOError writing file to output stream");
}
}
一般来说,当你有response.getOutputStream()时,你可以在那里写任何东西。您可以将此输出流作为将生成的PDF放置到生成器的位置。另外,如果你知道你要发送什么文件类型,你可以设置
response.setContentType("application/pdf");
我必须加上这个才能下载任何文件
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);
}
}
我能很快想到的是,生成pdf并将其存储在webapp/downloads/< RANDOM-FILENAME>.pdf代码中,并使用HttpServletRequest发送一个转发到这个文件
request.getRequestDispatcher("/downloads/<RANDOM-FILENAME>.pdf").forward(request, response);
或者你可以这样配置你的视图解析器,
<bean id="pdfViewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="viewClass"
value="org.springframework.web.servlet.view.JstlView" />
<property name="order" value=”2″/>
<property name="prefix" value="/downloads/" />
<property name="suffix" value=".pdf" />
</bean>
然后返回
return "RANDOM-FILENAME";
在Spring 3.0中,您可以使用HttpEntity返回对象。如果您使用它,那么您的控制器就不需要HttpServletResponse对象,因此它更容易测试。 除了这个,这个答案是相对等于Infeligo的答案。
如果你的pdf框架的返回值是一个字节数组(阅读我回答的其他返回值的第二部分):
@RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET)
public HttpEntity<byte[]> createPdf(
@PathVariable("fileName") String fileName) throws IOException {
byte[] documentBody = this.pdfFramework.createPdf(filename);
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_PDF);
header.set(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=" + fileName.replace(" ", "_"));
header.setContentLength(documentBody.length);
return new HttpEntity<byte[]>(documentBody, header);
}
如果你的PDF框架(documentBbody)的返回类型不是一个字节数组(也没有ByteArrayInputStream),那么它将是明智的不让它成为一个字节数组。相反,最好使用:
InputStreamResource, PathResource(从Spring 4.0开始)或 FileSystemResource,
使用FileSystemResource示例:
@RequestMapping(value = "/files/{fileName}", method = RequestMethod.GET)
public HttpEntity<byte[]> createPdf(
@PathVariable("fileName") String fileName) throws IOException {
File document = this.pdfFramework.createPdf(filename);
HttpHeaders header = new HttpHeaders();
header.setContentType(MediaType.APPLICATION_PDF);
header.set(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=" + fileName.replace(" ", "_"));
header.setContentLength(document.length());
return new HttpEntity<byte[]>(new FileSystemResource(document),
header);
}
在我的情况下,我需要生成一些文件,所以url也必须生成。
对我来说是这样的:
@RequestMapping(value = "/files/{filename:.+}", method = RequestMethod.GET, produces = "text/csv")
@ResponseBody
public FileSystemResource getFile(@PathVariable String filename) {
String path = dataProvider.getFullPath(filename);
return new FileSystemResource(new File(path));
}
非常重要的是,mime类型在produces中,文件名也是链接的一部分所以你必须使用@PathVariable。
HTML代码是这样的:
<a th:href="@{|/dbreport/files/${file_name}|}">Download</a>
其中${file_name}是由thymleaf在控制器中生成的,即:result_20200225.csv,因此链接的整个url是:example.com/aplication/dbreport/files/result_20200225.csv。
点击链接后,浏览器问我如何处理文件-保存或打开。