SpringBoot+Vue3實(shí)現(xiàn)文件的上傳和下載功能
前言
上傳文件和下載文件是我們平時(shí)經(jīng)常用到的功能,接下來就讓我們用SpringBoot,Vue3和ElementPlus組件實(shí)現(xiàn)文件的上傳和下載功能吧~
上傳前端頁面
前端頁面我們可以使用ElementPlus框架的el-upload組件完成上傳,主要的參數(shù)解釋如下:
- action屬性:指定請求的url
- onsuccess屬性: 請求成功后的回調(diào)函數(shù)
我們可以使用axios向后端發(fā)起get請求,然后后端返回文件保存的位置
表單項(xiàng)上傳框代碼如下:
<!-- 附件上傳 -->
<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單擊事件代碼如下
// 上傳文件返回函數(shù),為了得到后端返回的下載url,保存到數(shù)據(jù)庫中
uploadFileSuccess(response, file, fileList) {
let filePath = response.data;
// 上傳文件成功后的response參數(shù)已經(jīng)是返回報(bào)文中的data部分,不需要使用response.data.data
alert(response.data);
// 回調(diào)函數(shù)中的this指針就是當(dāng)前頁面vue對象
this.attachForm.downloadUrl = filePath;
}上傳后端代碼
Controller代碼如下:
@PostMapping("/uploadFile")
public String uploadFile(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws IllegalStateException, IOException{
// TODO: 文件保存文件夾,后期可以換成配置文件中的內(nèi)容
String path = "D:\\uploadfiles";
String result = "";
// 調(diào)用fileService保存文件
result = fileService.storeFile(file, path);
logger.info("文件已保存至" + result);
return result;
}fileService代碼如下:
/**
* 存儲文件到系統(tǒng)
*
* @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;
// //文件的保存重新按照時(shí)間戳命名
// 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();
}下載后端代碼
因?yàn)橄螺d的是文件,所以我們要指定content-type為"application/octet-stream;charset=utf-8"。當(dāng)文件名中含有中文字符時(shí),需要使用URLEncoder.encode(fileName, "UTF-8")轉(zhuǎn)碼,然后在前端在轉(zhuǎn)回來,否則會亂碼。
@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;
// 發(fā)送get請求
this.$axios
.get('/api/file/downloadFile', {
params: {
// 向后端傳入下載路徑
file: url,
}
})
.then(res => {
// alert("請求成功");
console.log(res.data); // 獲取服務(wù)端提供的數(shù)據(jù)
let blob = new Blob([res.data])
let contentDisposition = res.headers['content-disposition']
let pattern = new RegExp('filename=([^;]+\\.[^\\.;]+);*')
let result = pattern.exec(contentDisposition)
// 使用decodeURI對名字進(jìn)行解碼
let fileName = decodeURI(result[1])
let downloadElement = document.createElement('a')
// 創(chuàng)建下載的鏈接
let href = window.URL.createObjectURL(blob)
downloadElement.style.display = 'none'
downloadElement.href = href
// 下載后文件名
downloadElement.download = fileName
document.body.appendChild(downloadElement)
// 點(diǎn)擊下載
downloadElement.click()
// 下載完成移除元素
document.body.removeChild(downloadElement)
// 釋放掉blob對象
window.URL.revokeObjectURL(href)
})
.catch(() => {
alert("請求出錯");
})
// alert(url);
}總結(jié)
上傳下載文件中最讓我頭疼的是文件名包含中文問題,原先一直不了解不同字符集之間的區(qū)別,現(xiàn)在終于清楚點(diǎn)了,原來漢字在電腦里有一種單獨(dú)地唯一的存儲格式,稱為內(nèi)部碼。我們使用不同的字符集(如GBK,UTF-8)進(jìn)行編碼和解碼時(shí),只是在以不同的方式存儲這些內(nèi)部碼,以字節(jié)的形式存儲下來。
參考文獻(xiàn)
下載文件時(shí)文件名含有中文亂碼問題
Unicode、UTF-8 和 ISO8859-1到底有什么區(qū)別
到此這篇關(guān)于SpringBoot+Vue3實(shí)現(xiàn)文件的上傳和下載的文章就介紹到這了,更多相關(guān)vue3 springboot 文件上傳下載內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue2中使用SSE(服務(wù)器發(fā)送事件)原因分析
SSE是圍繞只讀Comet交互推出的API或者模式,SSE 支持短輪詢、長輪詢和HTTP 流,而且能在斷開連接時(shí)自動確定何時(shí)重新連接,本文重點(diǎn)給大家介紹2023-10-10
Vue3中結(jié)合ElementPlus實(shí)現(xiàn)彈窗的封裝方式
這篇文章主要介紹了Vue3中結(jié)合ElementPlus實(shí)現(xiàn)彈窗的封裝方式,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
Vue?監(jiān)視屬性之天氣案例實(shí)現(xiàn)
這篇文章主要介紹了Vue?監(jiān)視屬性之天氣案例實(shí)現(xiàn),文章以天氣為例展開介紹Vue?監(jiān)視屬性?的相關(guān)內(nèi)容,需要的小伙伴可以參考一下2022-05-05
vue2中的el-select組件數(shù)據(jù)太多,如何實(shí)現(xiàn)滾動加載數(shù)據(jù)效果
這篇文章主要介紹了vue2中的el-select組件數(shù)據(jù)太多,如何實(shí)現(xiàn)滾動加載數(shù)據(jù)效果,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-04-04

