【寫(xiě)在前面】前端時(shí)間總結(jié)了一下有關(guān)java文件上傳的功能,也給不少讀者帶來(lái)一些幫助,因此今天繼續(xù)完善文件下載這套體系,希望能給屏幕前的您帶來(lái)實(shí)質(zhì)性的幫助,其實(shí)文件下載最怕的就是中文亂碼的現(xiàn)象,當(dāng)然這個(gè)我單獨(dú)寫(xiě)了一篇文章解釋?zhuān)@里不做詳談。
涉及知識(shí)點(diǎn):encode和decode,java文件下載,文件下載中文名亂碼,F(xiàn)ileInputStream。
實(shí)現(xiàn)效果
1、功能分析
首先我們要做的是下載,和導(dǎo)出還是有一點(diǎn)區(qū)別的,下載是從目標(biāo)路徑(服務(wù)器)將指定的文件下載一份下來(lái)到客戶(hù)端的過(guò)程。
所以首先我們必須得知道您要下載的文件存放路徑及對(duì)應(yīng)的文件名,這個(gè)可以是前端傳遞,也可以是在接口指定,當(dāng)然一些固定的模板可以采用接口指定或者配置文件設(shè)置,要是一些動(dòng)態(tài)的列表中下載指定的文件的話最好是前端傳遞。
Java中獲取當(dāng)前class路徑的方式如下(我是獲取之前上傳后文件的路徑,基于本地):
String tempName="黃大大的街舞夢(mèng).xlsx";
String filePath=this.getClass().getResource("/template/"+tempName).getPath();
網(wǎng)上還有人說(shuō)要根據(jù)不同瀏覽器的User-Agent屬性值來(lái)做判斷,但是我發(fā)現(xiàn)IE,Chrome,Edge都是可行的
2、代碼實(shí)現(xiàn)
Java實(shí)現(xiàn)文件下載我們要從前后端兩方面入手,且要確保目標(biāo)路徑下有你要的文件,不然也會(huì)下載失敗的。
2.1 前端頁(yè)面搭建(vue)
創(chuàng)建一個(gè)節(jié)點(diǎn),主要用于觸發(fā)文件下載接口,我用的是vant3的按鈕,基于click事件進(jìn)行觸發(fā),如下所示:
<van-button type="primary" @click="Download()">下載文件</van-button>
然后再在methods里面封裝一個(gè)下載的方法,如下所示:
Download() {
axios
.get("/Updown/download", { responseType: "blob" })
.then((response) => {
console.log(response);
//headers請(qǐng)求頭的亂碼數(shù)據(jù)轉(zhuǎn)換為中文
const fileName = decodeURI(
response.headers["content-disposition"].split(";")[1].split("=")[1]
);
debugger;
//下載文件
let blob = new Blob([response.data], {
type: "application/vnd.ms-excel",
});
let objectUrl = URL.createObjectURL(blob); // 創(chuàng)建URL
const link = document.createElement("a");
link.href = objectUrl;
// link.download = '.xlsx'// 自定義文件名
//這里是獲取后臺(tái)傳過(guò)來(lái)的文件名
link.setAttribute("download", fileName);
link.click(); // 下載文件
URL.revokeObjectURL(objectUrl); // 釋放內(nèi)存
})
.catch((error) => {
console.log(error);
alert("下載失敗");
});
},
只有這個(gè)方法就可以實(shí)現(xiàn)下載功能
【前端劃重點(diǎn)】
請(qǐng)求方式:get的方式(post方式暫時(shí)沒(méi)有實(shí)測(cè),后續(xù)更新)
響應(yīng)類(lèi)型:responseType: “blob”,二進(jìn)制大對(duì)象類(lèi)型,存儲(chǔ)大量的二進(jìn)制和文本的容器。
編碼轉(zhuǎn)換:decodeURI,主要是和java的encode對(duì)應(yīng),因?yàn)橹形拿枰D(zhuǎn)一下,不然亂碼。
2.2 后臺(tái)接口實(shí)現(xiàn)(java)
Java下載文件其核心在于FileInputStream文件字節(jié)輸入流,也就是將文件變成機(jī)器識(shí)別的字節(jié),然后通過(guò)read方法,從文件的第一個(gè)字節(jié)開(kāi)始,read方法每執(zhí)行一次,就會(huì)將一個(gè)字節(jié)讀取,并返回該字節(jié)ASCII碼。
另外針對(duì)中文我們要加一個(gè)encode的編碼處理,方便傳輸不會(huì)出現(xiàn)中文名亂碼的現(xiàn)象。
Java實(shí)現(xiàn)核心代碼如下:
int len = filePath.lastIndexOf("/");
if (StringUtils.isBlank(filePath) || len == -1) {
throw new Exception("未上傳文件!");
}
String fileName = filePath.substring(len + 1);
File file = new File(filePath);
if (!file.exists()) {
throw new Exception("文件不存在!");
}
fileName = URLEncoder.encode(fileName, "UTF-8");
try {
response.setHeader("Content-disposition","attachment; filename="+ fileName);
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("UTF-8");
OutputStream out = response.getOutputStream();
BufferedInputStream fin = new BufferedInputStream(new FileInputStream(file));
try {
byte[] content = new byte[1024];
int length;
while ((length = fin.read(content, 0, content.length)) != -1) {
out.write(content, 0, length);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
logger.info("文件下載失敗", e.getMessage());
throw e;
} finally {
fin.close();
out.flush();
out.close();
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
throw e;
}
3、常見(jiàn)問(wèn)題
3.1 下載失敗
路徑問(wèn)題:首先確定路徑是對(duì)的,可以在后端打個(gè)斷點(diǎn)看filePath是否能在本地找到,不能找到肯定會(huì)導(dǎo)致失敗的。
請(qǐng)求方式問(wèn)題:請(qǐng)求方式是否前后端統(tǒng)一,別前端用了post后端用了get,這樣會(huì)導(dǎo)致接口調(diào)用失敗報(bào)錯(cuò)。
3.2 下載中文名亂碼、中文名下劃線、中文名百分號(hào)等現(xiàn)象。
編碼轉(zhuǎn)碼問(wèn)題:這個(gè)說(shuō)明接口通的,也能實(shí)現(xiàn)java文件下載了,但是中文名沒(méi)有進(jìn)行encode編碼和decode轉(zhuǎn)碼的步驟,所以這個(gè)時(shí)候應(yīng)該好好排查一下java的編碼和vue的轉(zhuǎn)碼。文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-487399.html
4、皇榜彩蛋
傾心打造佳作,愿解君之惑,如若有幸,盼君上榜助陣,特此敬謝!
皇榜入口點(diǎn)擊此處文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-487399.html
到了這里,關(guān)于【Java 實(shí)現(xiàn)文件下載】vue前端+java后端實(shí)現(xiàn)文件下載詳解(附源碼)的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!