需要下载文件,又想在浏览器页面弹出下载成功的弹窗,便于直接打开。这里主要是为了使用户可以在浏览器页面就可以看见模板下载成功的弹窗。
这里代码是完整,可直接放心使用。
目标效果:类似于这样 ==》浏览器弹出的下载成功弹窗:
目录
1、依赖
使用hutool包
<!-- hutool工具类 版本:<hutool.version>5.3.8</hutool.version> -->
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-core</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-crypto</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-extra</artifactId>
<version>5.3.8</version>
</dependency>
<dependency>
<groupId>cn.hutool</groupId>
<artifactId>hutool-http</artifactId>
<version>5.3.8</version>
</dependency>
2、后端代码
接口和方法:
将文件转换为二进制流返回给前端
这里将静态资源的文件先下载读取,再写入到本地电脑的文件中。
目的:防止有些idea运行项目时,使用了热部署插件,会让class文件动态加载,导致在读取静态资源的文件无法获取,所以先将该静态资源文件下载。
* 下载文件模板
*/
@RequestMapping(value = "/downLoadTem")
public void downLoadTem(HttpServletResponse response) throws IOException {
convertFileToOctetStream(response);
}
/**
* 将文件转换为二进制流返回给前端
*/
public static void convertFileToOctetStream(HttpServletResponse response) throws IOException {
//静态资源下的文件相对路径
String s = "static" + File.separator + "文件模版.xls";
//从静态资源中读取文件模板,获取改文件的字节流形式的数据
ClassPathResource resource = new ClassPathResource(s);
String absolutePath = resource.getFile().getAbsolutePath();
InputStream stream = new FileInputStream(absolutePath);
String tempPath = "D:\\demo\\templateExpertExcel\\文件模版.xls";
//这里将静态资源的文件先下载读取,再写入到本地电脑的文件中
//目的:防止有些idea运行项目时,使用了热部署插件,会让class文件动态加载,导致在读取静态资源的文件无法获取,所以先将该静态资源文件下载
Path filePath = Paths.get(tempPath);
if (!Files.exists(filePath)) {
//判断该路径文件是否存在,如果不存在则创建
Files.createDirectories(filePath.getParent());
Files.createFile(filePath);
}
try (OutputStream fos = Files.newOutputStream(filePath)) {
byte[] buffer = new byte[1024];
int len;
while ((len = stream.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
} finally {
stream.close();
}
//写到这里,如果前端不需要回显下载的样式,下面的代码就不需要了,找个时候文件模板已经下载到目标目录了(String tempPath = "D:\\demo\\templateExpertExcel\\文件模版.xls";
)
//-----------------------------------------------------
try {
// 将下载的Excel文件转换为流
File file1 = new File(tempPath);
InputStream inputStream = new FileInputStream(file1);
// 将流响应给前端回显
response.setContentType("application/octet-stream");
OutputStream outputStream = response.getOutputStream();
byte[] buffer1 = new byte[1024];
int len1;
while ((len1 = inputStream.read(buffer1)) > 0) {
outputStream.write(buffer1, 0, len1);
}
outputStream.flush();
outputStream.close();
inputStream.close();
} catch (Exception e) {
log.error("下载文件模版异常");
}
}
3、前端代码
这里前端使用vue2
按钮:
<button @click="downLoadTem">下载文件模板</button>
方法:
methods: {
// 下载模板
downLoadTem() {
this.downloadFile(`/downLoadTem`, `文件模板.xls`)
.then(() => {
this.$message.success('下载成功!')
})
.catch(() => {
this.$message.error('下载失败!')
})
},
/* 文件下载 */
downloadFile(text){
if(!text){
this.$message.warning("未知的文件")
return;
}
if(text.indexOf(",")>0){
text = text.substring(0,text.indexOf(","))
}
let url = this.getFileAccessHttpUrl(text)
window.open(url);
},
/**
* 获取文件服务访问路径
* @param avatar
* @param subStr
* @returns {*}
*/
getFileAccessHttpUrl(avatar,subStr) {
if(!subStr) subStr = 'http'
try {
if(avatar && avatar.startsWith(subStr)){
return avatar;
}else{
if(avatar && avatar.length>0 && avatar.indexOf('[')==-1){
return window._CONFIG['staticDomainURL'] + "/" + avatar;
}
}
}catch(err){
return;
}
}
4、特别注意--文件下载成功后却乱码的情况
需要将word模板放在项目的static的静态资源下,路径格式如下:
需要注意的是:如果项目是父子工程的,将这个文件模板放在父工程的静态资源中
在父工程中:
在对应块中添加这个代码即可,避免被压缩破坏
<build> <plugins> <!-- 避免font文件的二进制文件格式压缩破坏 --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-resources-plugin</artifactId> <configuration> <nonFilteredFileExtensions> <nonFilteredFileExtension>docx</nonFilteredFileExtension> </nonFilteredFileExtensions> </configuration> </plugin> </plugins> </build>
最核心的代码就是这行:
<nonFilteredFileExtension>docx</nonFilteredFileExtension>