文件下载
Web 文件下载
服务端返回文件流
我们只需要直接将后端返回的文件流以新的窗口打开,即可直接下载了。
// 前端代码
<button id="oBtnDownload">点击下载</button>
<script>
oBtnDownload.onclick = function() {
window.open(
"http://localhost:8888/api/download?filename=1597375650384.jpg",
"_blank"
);
};
</script>
// 后端代码
router.get("/api/download", async (ctx) => {
const { filename } = ctx.query;
const fStats = fs.statSync(path.join(__dirname, "./static/", filename));
ctx.set({
"Content-Type": "application/octet-stream",
"Content-Disposition": `attachment; filename=${filename}`,
"Content-Length": fStats.size,
});
ctx.body = fs.readFileSync(path.join(__dirname, "./static/", filename));
});
浏览器文件自动下载
能够让浏览器自动下载文件,主要有两种情况
Content-Disposition
在常规的
Content-Disposition: inline
Content-Disposition: attachment
Content-Disposition: attachment; filename="filename.jpg"
浏览器无法识别
例如输入nginx
少了这一行配置
include mime.types;
导致默认走了 application/octet-stream
,浏览器无法识别就下载了文件。
后端返回静态站点地址
通过静态站点下载,这里要分为两种情况,一种为可能该服务自带静态目录,即为同源情况,第二种情况为适用了第三方静态存储平台,例如阿里云、腾讯云之类的进行托管,即非同源(当然也有些平台直接会返回
同源
同源情况下是非常简单,先上代码,直接调用一下函数就能轻松实现下载。
import { downloadDirect } from "../js/utils.js";
axios.get("http://localhost:8888/api/downloadUrl").then((res) => {
if (res.data.code === 0) {
downloadDirect(res.data.data.url);
}
});
非同源
我们也可以从

<button id="oBtnDownload">点击下载</button>
<script type="module">
import { downloadByBlob } from "../js/utils.js";
function download(url) {
axios({
method: "get",
url,
responseType: "blob",
}).then((res) => {
downloadByBlob(res.data, url.split("/").pop());
});
}
oBtnDownload.onclick = function() {
axios.get("http://localhost:8888/api/downloadUrl").then((res) => {
if (res.data.code === 0) {
download(res.data.data.url);
}
});
};
</script>
后端返回字符串(base64)
// node 端
router.get("/api/base64", async (ctx) => {
const { filename } = ctx.query;
const content = fs.readFileSync(path.join(__dirname, "./static/", filename));
const fStats = fs.statSync(path.join(__dirname, "./static/", filename));
console.log(fStats);
ctx.body = {
code: 0,
data: {
base64: content.toString("base64"),
filename,
type: mime.getType(filename),
},
};
});
// 前端
<button id="oBtnDownload">点击下载</button>
<script type="module">
function base64ToBlob(base64, type) {
const byteCharacters = atob(base64);
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
const buffer = Uint8Array.from(byteNumbers);
const blob = new Blob([buffer], { type });
return blob;
}
function download({ base64, filename, type }) {
const blob = base64ToBlob(blob, type);
downloadByBlob(blob, filename);
}
oBtnDownload.onclick = function () {
axios
.get("http://localhost:8888/api/base64?filename=1597375650384.jpg")
.then((res) => {
if (res.data.code === 0) {
download(res.data.data);
}
});
};
</script>
思路其实还是利用了我们上面说的 标签。但是在这个步骤前,多了一个步骤就是,需要将我们的