SpringBoot+Vue3实现文件的上传和下载功能
目录
- 前言
- 上传前端页面
- 上传后端代码
- 下载后端代码
- 总结
- 参考文献
前言
上传文件和下载文件是我们平时经常用到的功能,接下来就让我们用SpringBoot
,Vue3
和ElementPlus
组件实现文件的上传和下载功能吧~
上传前端页面
前端页面我们可以使用ElementPlus
框架的el-upload
组件完成上传,主要的参数解释如下:
- action属性:指定请求的url
- onsuccess属性: 请求成功后的回调函数
我们可以使用axios
向后端发起get
请求,然后后端返回文件保存的位置
表单项上传框代码如下:
<!-- 附件上传 --> <el-form-item label="上传图片" ref="uploadElement"> <el-upload class="upload-demo" action="/api/file/uploadFile" :limit="5" :on-success="uploadFileSuccess" > <el-button type="primary">添加附件</el-button> <template #tip> <div class="el-upload__tip"> pdf, md, word格式均可 </div> </template> </el-upload> </el-form-item>
js单击事件代码如下
// 上传文件返回函数,为了得到后端返回的下载url,保存到数据库中 uploadFileSuccess(response, file, fileList) { let filePath = response.data; // 上传文件成功后的response参数已经是返回报文中的data部分,不需要使用response.data.data alert(response.data); // 回调函数中的this指针就是当前页面vue对象 this.attachForm.downloadUrl = filePath; }
上传后端代码
Controller代码如下:
@PostMapping("/uploadFile") public String uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException{ // TODO: 文件保存文件夹,后期可以换成配置文件中的内容 String path = "D:\\uploadfiles"; String result = ""; // 调用fileService保存文件 result = fileService.storeFile(file, path); logger.info("文件已保存至" + result); return result; }
fileService代码如下:
/** * 存储文件到系统 * * @param file 文件 * @path 保存路径 * @return 文件名 * @throws IOException * @throws IllegalStateException */ @Override public String storeFile(MultipartFile file, String path) throws IllegalStateException, IOException { // 获取原始文件名 String fileName = file.getOriginalFilename(); // // 获取文件后缀 // String suffixName = fileName.contains(".") ? fileName.substring(fileName.lastIndexOf(".")) : null; // //文件的保存重新按照时间戳命名 // String newFileName = System.currentTimeMillis() + suffixName; // 最终保存的文件 File filePath = new File(path + File.separator + fileName); // 判断文件夹是否存在 if (!filePath.getParentFile().exists()) { filePath.getParentFile().mkdirs(); } // 保存文件 file.transferTo(filePath); // 如果成功,会返回文件的绝对路径,方便下载 logger.info("文件已保存至" +filePath.toString()); return filePath.toString(); }
下载后端代码
因为下载的是文件,所以我们要指定content-type
为"application/octet-stream;charset=utf-8"
。当文件名中含有中文字符时,需要使用URLEncoder.encode(fileName, "UTF-8")
转码,然后在前端在转回来,否则会乱码。
@RequestMapping("/downloadFile") public void downloadFiles(@RequestParam("file") String downUrl, HttpServletRequest request, HttpServletResponse response){ OutputStream outputStream=null; InputStream inputStream=null; BufferedInputStream bufferedInputStream=null; byte[] bytes=new byte[1024]; File file = new File(downUrl); String fileName = file.getName(); logger.info("本次下载的文件为" + downUrl); // 获取输出流 try { // StandardCharsets.ISO_8859_1 *=UTF-8' // response.setHeader("Content-Disposition", "attachment;filename=" + new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); // 以流的形式返回文件 response.setContentType("application/octet-stream;charset=utf-8"); inputStream = new FileInputStream(file); bufferedInputStream = new BufferedInputStream(inputStream); outputStream = response.getOutputStream(); int i = bufferedInputStream.read(bytes); while (i!=-1){ outputStream.write(bytes,0,i); i = bufferedInputStream.read(bytes); } } catch (IOException e) { e.printStackTrace(); }finally { try { if (inputStream!=null){ inputStream.close(); } if (outputStream!=null){ outputStream.close(); } if (bufferedInputStream!=null){ bufferedInputStream.close(); } } catch (IOException e) { e.printStackTrace(); } }
- 下载前端代码 为了让浏览器弹出下载提示框,我们需要在前端做一下处理。
- 在前端使用
decodeURI
对文件解码。
downloadAttach(url) { let _this = this; // 发送get请求 this.$axios .get('/api/file/downloadFile', { params: { // 向后端传入下载路径 file: url, } }) .then(res => { // alert("请求成功"); console.log(res.data); // 获取服务端提供的数据 let blob = new Blob([res.data]) let contentDisposition = res.headers['content-disposition'] let pattern = new RegExp('filename=([^;]+\\.[^\\.;]+);*') let result = pattern.exec(contentDisposition) // 使用decodeURI对名字进行解码 let fileName = decodeURI(result[1]) let downloadElement = document.createElement('a') // 创建下载的链接 let href = window.URL.createObjectURL(blob) downloadElement.style.display = 'none' downloadElement.href = href // 下载后文件名 downloadElement.download = fileName document.body.appendChild(downloadElement) // 点击下载 downloadElement.click() // 下载完成移除元素 document.body.removeChild(downloadElement) // 释放掉blob对象 window.URL.revokeObjectURL(href) }) .catch(() => { alert("请求出错"); }) // alert(url); }
总结
上传下载文件中最让我头疼的是文件名包含中文问题,原先一直不了解不同字符集之间的区别,现在终于清楚点了,原来汉字在电脑里有一种单独地唯一的
存储格式,称为内部码
。我们使用不同的字符集(如GBK,UTF-8)进行编码和解码时,只是在以不同的方式存储这些内部码,以字节的形式存储下来。
参考文献
下载文件时文件名含有中文乱码问题
Unicode、UTF-8 和 ISO8859-1到底有什么区别
到此这篇关于SpringBoot+Vue3实现文件的上传和下载的文章就介绍到这了,更多相关vue3 springboot 文件上传下载内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!
赞 (0)