前言:
前端项目基于vue的,后端是springboot,文件上传后保存在文件服务器,同时文件服务器返回文件的访问路径,
当需要下载时,为了不让每个人都能通过页面a标签点击链接直接保存到本地,所以采用后台临时下载,返回文件流给前端,前端解析文件流,通过浏览器下载到浏览器存储目录中
1.用户点击请求下载文件
2.后端根据请求中的URL路径使用Java NIO下载文件,临时保存到下载服务器本地
3.通过文件流读取服务器本地文件,创建输出流,响应给前端
1.前端代码
<a @dblclick="downloadFile(item.url)" title="双击下载文件" v-else class="pointer"
style="display:block;width: 76px;height: 76px;overflow:hidden;word-wrap:break-word;line-height: 14px;background: #dedede;">
{{item.url.substring(item.url.lastIndexOf('/')+1,item.url.length)}}</a>
<script>
import {postFileDownload} from '../../../api/api'
export default {
methods:{
downloadFile(url){// 下载文件
postFileDownload({url:url})
}
}
}
</script>
api.js
import axios from '../assets/js/http'
export const postFileDownload = params =>{return axios.get('/fileAPI/downloadFile',{params:params},{responseType:'blob'}).then(res=>{
if(res.data && res.data.code === '-1')return;
let blob = new Blob([res.data]);
let fileName = res.headers.contentfilename;
if ('download' in document.createElement('a')) { // 非IE下载
let elink = document.createElement('a');
elink.download = fileName;
elink.style.display = 'none';
elink.href = URL.createObjectURL(blob);
document.body.appendChild(elink);
elink.click();
URL.revokeObjectURL(elink.href); // 释放URL
document.body.removeChild(elink)
} else {
navigator.msSaveBlob(blob, fileName)
}
})};
2.后端代码
控制层 , 权限这里只是测试,因为项目中有权限控制类,对接就好
@RequestMapping(value = "/downloadFile",method = RequestMethod.GET)
public Map downloadByURL(String url,HttpServletResponse res, HttpServletRequest req) throws IOException{
System.out.println("url:::::::::"+url);
Map map = new HashMap();
String auth = "Y";
if(auth.equals("N")){// 如果没有权限 只返回
map.put("code", "-1");
map.put("desc", "没有权限");
return map;
}
try {
fileDownloadUtil.downloadFile(url,res,req);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
下载工具类
/**
* 下载文件
* @param path 文件的位置
* @param fileName 自定义下载文件的名称
* @param resp http响应
* @param req http请求
* @throws Exception
*/
public static void downloadFile(String url, HttpServletResponse res, HttpServletRequest req) throws Exception{
String charsetCode = "utf-8";
String fileName = url.substring(url.lastIndexOf('\\')+1,url.length());
FileInputStream in = null;
OutputStream out = null;
try {
// 获取文件路径后先下载到服务器本地,返回服务器文件地址
String path = downloadFileByNIO(url);
System.out.println(path);
File file = new File(path);
/**
* 文件名中文乱码处理
*/
System.out.println("fileName:::::" + fileName);
String type = req.getHeader("User-Agent").toLowerCase();
if(type.indexOf("firefox")>0 || type.indexOf("chrome")>0){// 非IE
fileName = new String(fileName.getBytes(charsetCode), "iso8859-1");
}else{
fileName = URLEncoder.encode(fileName, charsetCode);
}
// 设置响应的头部信息
res.setHeader("contentfileName", fileName);
// 设置响应内容的类型
res.setContentType("application/json;charset=" + charsetCode);
// 设置响应内容的长度
res.setContentLength((int) file.length());
//读取要下载的文件,保存到文件输入流
in= new FileInputStream(file);
//创建输出流
out= res.getOutputStream();
//缓存区
byte[] buffer = new byte[1024];
int length = -1;
while ((length = in.read(buffer)) != -1) {
out.write(buffer, 0, length);
out.flush();
}
// 删除文件
delFile(file);
} catch (Exception e) {
e.printStackTrace();
throw e;
}finally{
try {
out.close();
} catch (IOException e) {
}
try {
in.close();
} catch (IOException e) {
}
}
}
/**
* 使用NIO下载文件
* @param url 下载的文件路径
*/
public static String downloadFileByNIO(String url) {
String saveDir = "E:\\HZ\\";
String fileName = url.substring(url.lastIndexOf('/') > (url.startsWith("http:") ? 6 :7)
? url.lastIndexOf('/') + 1 : url.lastIndexOf('\\') + 1,url.length());
url = url.replace('\\', '/');
try (InputStream ins = new URL(url).openStream()) {
Path targetPath = Paths.get(saveDir, fileName);
Files.createDirectories(targetPath.getParent());
Files.copy(ins, targetPath, StandardCopyOption.REPLACE_EXISTING);
// System.out.println(saveDir + fileName);
return saveDir + fileName;
} catch (IOException e) {
e.printStackTrace();
return null;
}
}
/**
* 删除文件
* @param file
* @return
*/
public static boolean delFile(File file) {
System.out.println("删除文件:" + file);
if (!file.exists()) {
return false;
}
boolean flag = file.delete();
System.out.println(flag);
return flag;
}
完结,存在的问题,删除文件失败,用main方法测试是可以的,返回true,但是请求调用时false,有谁找出问题所在,请留言,万分谢谢
附上main方法测试代码,郁闷中
public static void main(String args[]){
delFile(new File("E:\\HZ1\\hz1577340815468.exe"));
}