前話:
1. 在實(shí)際開(kāi)發(fā)過(guò)程中,實(shí)現(xiàn)文件下載功能,后端一般是返回一個(gè)文件流,我們只需要拿到這個(gè)文件流后,再使用new Blob轉(zhuǎn)化成blob格式的數(shù)據(jù),然后創(chuàng)建一個(gè)a鏈接元素進(jìn)行下載就行了:
(“本段代碼是之前寫(xiě)案例時(shí)從別處copy的,都有注釋省了自己寫(xiě),哈哈哈,侵刪”)
fetch("后端給的下載功能的url", {
method: "get",
})
.then((res) => {
console.log(res, "文件流對(duì)象---------,可以打印下來(lái)看看");
// 創(chuàng)建blob對(duì)象,將二進(jìn)制數(shù)據(jù)封裝為BLOB對(duì)象
const blob = new Blob([res], {
// 如何后端沒(méi)返回下載文件類(lèi)型,則需要手動(dòng)設(shè)置:type: 'application/pdf;chartset=UTF-8' 表示下載文檔為pdf,如果是word則設(shè)置為msword,excel為excel
type: type
})
const a = document.createElement("a");
// 兼容webkix瀏覽器,處理webkit瀏覽器中herf自動(dòng)添加blob前綴,默認(rèn)在瀏覽器打開(kāi)而不是下載
const URL = window.URL || window.webkitURL;
// 根據(jù)blob對(duì)象創(chuàng)建URL 對(duì)象,生成本地URL
const herf = URL.createObjectURL(blob);
// 下載鏈接
a.href = herf;
// 下載文件名,如果后端沒(méi)有返回,可以自己寫(xiě)a.download = '文件.pdf'
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
// 在內(nèi)存中移除URL 對(duì)象
URL.revokeObjectURL(herf);
});
});
2. 但是這次后端直接給我返回了個(gè)url地址:http://127.0.0.1:3000/attchment/test.png,再用這種方式就不適合了,如果拿到結(jié)果直接硬塞進(jìn)去發(fā)現(xiàn)不得行,瀏覽器對(duì)于 txt、png、jpeg 等這些后綴的文件會(huì)直接新窗口打開(kāi),讓你進(jìn)行預(yù)覽,并不會(huì)執(zhí)行下載操作;看到這里你是不是也頭大了?我也是,后面就想著既然上面這種方式是通過(guò)文件流下載的,那我拿到url的地址后,把url地址文件里面的內(nèi)容轉(zhuǎn)為blob文件流不就好了?說(shuō)干就干:
fetch(
"后端給你的下載地址的url",{
method: "get",
}
.then((response) => response.json())
.then((res) => {
console.log(res, "res--------------拿到后端返回的url");
// window.open(res.url)
fetch(res.url, {
method: "get",
responseType: "blob",
})
.then((response) => response.blob())
.then((blob) => {
const a = document.createElement("a");
const URL = window.URL || window.webkitURL;
// 根據(jù)blob對(duì)象創(chuàng)建URL 對(duì)象,生成本地URL
const herf = URL.createObjectURL(blob);
a.href = herf;
// 下載文件名,如果后端沒(méi)有返回,可以自己寫(xiě)a.download = '文件.pdf'
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
// 在內(nèi)存中移除URL 對(duì)象
URL.revokeObjectURL(herf);
});
});
按上面的方式,請(qǐng)求后端的下載功能接口后,拿到url再進(jìn)行一次請(qǐng)求,然后就可以通過(guò)返回值拿到文件流,再使用第一種傳統(tǒng)方式就可以實(shí)現(xiàn)下載了。
后言:
注意:由于后端返回的url地址和我們的前端項(xiàng)目地址存在跨域問(wèn)題,所以我們需要配置proxy代理,部署上線需要配置nginx反向代理配置,或者后端直接配置cors文章來(lái)源:http://www.zghlxwxcb.cn/news/detail-766863.html
server {
listen 80;
server_name www.xxxxx.cn;
location ^~ /attchment/ {
proxy_pass http://127.0.0.1:3000/;
}
}
后端示例代碼,可參考測(cè)試:文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-766863.html
const express = require("express")
const router = express()
const multer = require("multer");
const fs = require("fs")
const cors = require('cors'); //allow CORS
router.use(cors());
//存儲(chǔ)靜態(tài)資源文件位置,方便前端直接通過(guò)url拿取
router.use(express.static("./upload"))
router.post("/upload",multer({
dest:"upload"
}).single("file"),(req,res)=>{
console.log(req.file)
//處理上傳操作存儲(chǔ)起來(lái),存當(dāng)前文件夾或者mysql數(shù)據(jù)庫(kù)
})
router.get("/download",(req,res)=>{
req.query.url ? res.download(`upload/${req.query.url}`) : res.send({
success:false
})
res.send({
url:"http://localhost:3000/"+req.query.url
})
})
router.listen(3000,()=>{
console.log("服務(wù)開(kāi)啟在3000端口")
})
到了這里,關(guān)于后端返回URL,前端如何實(shí)現(xiàn)下載的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!