【发布时间】:2020-10-17 21:04:31
【问题描述】:
我想从我的应用使用 Node.js 和 Express.js 运行的同一台服务器(没有外部云文件存储,也就是本地)实现一个大文件下载(大约 10-1024 Mb)。
我想出了如何做到这一点,方法是将整个文件转换为Blob,通过网络传输,然后为Blob 生成带有window.URL.createObjectURL(…) 的下载链接。只要文件很小,这种方法就可以完美地工作,否则不可能将整个Blob保留在服务器和客户端的RAM中。
我尝试使用 File API 和 AJAX 实现其他几种方法,但看起来 Chrome 将整个文件加载到 RAM 中,然后才将其转储到磁盘。同样,对于小文件可能还可以,但对于大文件,这不是一种选择。
我最后一次尝试是发送一个基本的Get-request:
const aTag = document.createElement("a");
aTag.href = `/downloadDocument?fileUUID=${fileName}`;
aTag.download = fileName;
aTag.click();
在服务器端:
app.mjs
app.get("/downloadDocument", async (req, res) => {
req.headers.range = "bytes=0";
const [urlPrefix, fileUUID] = req.url.split("/downloadDocument?fileUUID=");
const downloadResult = await StorageDriver.fileDownload(fileUUID, req, res);
});
StorageDriver.mjs
export const fileDownload = async function fileDownload(fileUUID, req, res) {
//e.g. C:\Users\User\Projects\POC\assets\wanted_file.pdf
const assetsPath = _resolveAbsoluteAssetsPath(fileUUID);
const options = {
dotfiles: "deny",
headers: {
"Content-Disposition": "form-data; name=\"files\"",
"Content-Type": "application/pdf",
"x-sent": true,
"x-timestamp": Date.now()
}
};
res.sendFile(assetsPath, options, (err) => {
if (err) {
console.log(err);
} else {
console.log("Sent");
}
});
};
当我单击该链接时,Chrome 会在“下载”中显示该文件,但状态为 失败 - 无文件。下载目标中没有文件。
我的问题:
- 为什么在发送
Get-request 的情况下我得到Failed - No file? - 据我了解,
res.sendFile可以是小文件的正确选择,但对于大文件,最好使用res.write,它可以分成块。是否可以将res.write与Get-request 一起使用?
附:我已经详细说明了这个问题,以使其更加狭窄和清晰。以前这个问题的重点是从 Dropbox 下载一个大文件而不将其存储在 RAM 中,可以找到答案: How to download a big file from Dropbox with Node.js?
【问题讨论】:
标签: javascript node.js download data-transfer chunking