踩坑记录—springboot实现下载文件以及踩坑记录
一.背景
今天本来有个小需求,就是通过接口来获取一个docx文件,很简单,但是万万没想到啊!!!还是踩坑了。顺便做个记录吧。废话不多说,进入正题。
二. SpringBoot获取resources下的静态资源
ClassPathResource cpr = new ClassPathResource(path);
File file = cpr.getFile();
说明:这里的path为文件相对路径,不要有/开头, 文件的路径分隔符使用:File.separator
三. 踩坑记录
获取到文件之后我就觉得可以了,但是测试的时候发现了一个问题,提示文件已经被损坏了。
文件打不开截图
后来发现是因为 target 文件夹生成时损坏了docx文件的内容,我们用的maven,所以需要禁用对文件的过滤。
对maven的配置
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<configuration>
<nonFilteredFileExtensions>
<nonFilteredFileExtension>docx</nonFilteredFileExtension>
</nonFilteredFileExtensions>
</configuration>
</plugin>
又因为是springboot项目,如果需要打jar包的话,在文件编译时,需要将 resource 目录下的文件拷贝到 target 目录的 classes 目录下面,所以呢新增
<resources>
<!-- 把资源文件拷贝到classs目录下 否则打成jar包后会找不到静态资源-->
<resource>
<targetPath>${project.build.directory}/classes</targetPath>
<directory>src/main/resources</directory>
<!-- 开启过滤,用指定的参数替换directory下的文件中的参数 -->
<filtering>true</filtering>
<!-- 指定具体的文件,带扩展名 -->
<includes>
<include>**/*.docx</include>
</includes>
</resource>
<resource>
<targetPath>${project.build.directory}/classes</targetPath>
<directory>src/main/resources</directory>
<!-- 不开启过滤 -->
<filtering>false</filtering>
<includes>
<!-- 改匹配规则是将 resource 目录下的所有文件夹及文件都包含 -->
<include>**/*</include>
</includes>
</resource>
</resources>
完整代码
/**
* @param response
* @功能描述 下载文件
*/
@PostMapping("/download")
public void downloadLocal(HttpServletResponse response) {
try {
String path = "file" + File.separator + "xxx.docx";
ClassPathResource cpr = new ClassPathResource(path);
InputStream inputStream = cpr.getInputStream();
response.reset();
response.setContentType("application/octet-stream");
String filename = cpr.getFilename();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(filename, "UTF-8"));
ServletOutputStream outputStream = response.getOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) > 0) {
outputStream.write(buffer, 0, len);
}
} catch (IOException e) {
e.printStackTrace();
}finally {
// 关流
}
}