如何使用 Node.js 从 Dropbox 下载大文件?
How to download a big file from Dropbox with Node.js?
我想实现大文件下载(大约 10-1024 Mb)。我已经成功从 Dropbox 获取文件:
operationResult = await dbx.filesDownload({
path: `/${CONFIG_STORAGE.uploader.assetsPath}/${fileUUID}`
});
然后我将接收到的文件与元数据捆绑在一起,然后 return 将其发送到我的 Node.js 服务器:
fileMIME = mime.lookup(operationResult.name);
const downloadResult = Object.freeze({
fileBinary: operationResult.fileBinary,
fileLength: operationResult.fileBinary.length,
fileMIME,
fileName: operationResult.name,
isSucceeded,
message
});
return downloadResult;
现在我将从 Dropbox 获得的 Buffer
转换为 Readable
流并将其通过管道返回给客户端:
res.setHeader("Content-Disposition", "attachment; filename=" + downloadResult.fileName);
res.setHeader("Content-Type", downloadResult.fileMIME);
const fileReadableStream = new Readable();
fileReadableStream.push(downloadResult.fileBinary);
fileReadableStream.push(null);
fileReadableStream.pipe(res);
到目前为止,一切都很清楚并且可以正常工作。在这里我遇到了第一个陷阱:我需要以某种方式在浏览器中触发下载过程。
在很多示例中,使用了一些小图像或JSON,我们可以将其完全加载到RAM中,进行操作,例如转化为Base64
,赋值给a.href
,触发a.click()
。但是由于我的文件是 10-50 Mb,我不确定这种方法是否正确。
我已经试过 Fetch API:
const response = await fetch(`${host}/download?fileName=${fileName}`, {
credentials: "same-origin",
method: "POST",
mode: "cors"
});
const a = document.createElement("a");
a.href = response.text();
a.download = "MyFile.pdf";
a.click();
但我总是收到 失败 - 无文件 错误。我也试过用jQueryAJAX和XMLHttpRequest
(XHR
),但还是没有文件下载。
也许,我缺少了什么。如何从服务器获取 10-1024 Mb 的文件?
P.S。没想到下载文件这么简单的事情,竟然会这么复杂。
我通过从 filesDownload
切换到 filesGetTemporaryLink
解决了这个问题,其中 returns 和 link 切换到文件而不是文件本身。然后我触发下载这个 link.
最终结果:
operationResult = await dbx.filesGetTemporaryLink({
path: `/${CONFIG_STORAGE.uploader.assetsPath}/${fileUUID}`
});
const downloadResult = Object.freeze({
fileLength: operationResult?.metadata.size,
fileLink: operationResult?.link,
fileMIME: mime.lookup(operationResult?.metadata.name),
fileName: operationResult?.metadata.name,
isSucceeded,
message
});
return downloadResult;
然后我将输出发送给客户端:
res.json(downloadResult);
在客户端,我通过 await
/async
Fetch API 调用获取它:
const fileResponse = await fetch(``${host}/downloadDocument`, {
body: JSON.stringify({fileUUID: fileName}),
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json"
},
method: "POST",
mode: "cors"
});
const fileData = await fileResponse.json();
const aTag = document.createElement("a");
aTag.href = fileData.fileLink;
aTag.download = fileData.fileName;
aTag.click();
因此,服务器根本不需要处理文件,没有额外的 CPU、RAM 或流量影响,无论我尝试下载的文件有多大。
我想实现大文件下载(大约 10-1024 Mb)。我已经成功从 Dropbox 获取文件:
operationResult = await dbx.filesDownload({
path: `/${CONFIG_STORAGE.uploader.assetsPath}/${fileUUID}`
});
然后我将接收到的文件与元数据捆绑在一起,然后 return 将其发送到我的 Node.js 服务器:
fileMIME = mime.lookup(operationResult.name);
const downloadResult = Object.freeze({
fileBinary: operationResult.fileBinary,
fileLength: operationResult.fileBinary.length,
fileMIME,
fileName: operationResult.name,
isSucceeded,
message
});
return downloadResult;
现在我将从 Dropbox 获得的 Buffer
转换为 Readable
流并将其通过管道返回给客户端:
res.setHeader("Content-Disposition", "attachment; filename=" + downloadResult.fileName);
res.setHeader("Content-Type", downloadResult.fileMIME);
const fileReadableStream = new Readable();
fileReadableStream.push(downloadResult.fileBinary);
fileReadableStream.push(null);
fileReadableStream.pipe(res);
到目前为止,一切都很清楚并且可以正常工作。在这里我遇到了第一个陷阱:我需要以某种方式在浏览器中触发下载过程。
在很多示例中,使用了一些小图像或JSON,我们可以将其完全加载到RAM中,进行操作,例如转化为Base64
,赋值给a.href
,触发a.click()
。但是由于我的文件是 10-50 Mb,我不确定这种方法是否正确。
我已经试过 Fetch API:
const response = await fetch(`${host}/download?fileName=${fileName}`, {
credentials: "same-origin",
method: "POST",
mode: "cors"
});
const a = document.createElement("a");
a.href = response.text();
a.download = "MyFile.pdf";
a.click();
但我总是收到 失败 - 无文件 错误。我也试过用jQueryAJAX和XMLHttpRequest
(XHR
),但还是没有文件下载。
也许,我缺少了什么。如何从服务器获取 10-1024 Mb 的文件?
P.S。没想到下载文件这么简单的事情,竟然会这么复杂。
我通过从 filesDownload
切换到 filesGetTemporaryLink
解决了这个问题,其中 returns 和 link 切换到文件而不是文件本身。然后我触发下载这个 link.
最终结果:
operationResult = await dbx.filesGetTemporaryLink({
path: `/${CONFIG_STORAGE.uploader.assetsPath}/${fileUUID}`
});
const downloadResult = Object.freeze({
fileLength: operationResult?.metadata.size,
fileLink: operationResult?.link,
fileMIME: mime.lookup(operationResult?.metadata.name),
fileName: operationResult?.metadata.name,
isSucceeded,
message
});
return downloadResult;
然后我将输出发送给客户端:
res.json(downloadResult);
在客户端,我通过 await
/async
Fetch API 调用获取它:
const fileResponse = await fetch(``${host}/downloadDocument`, {
body: JSON.stringify({fileUUID: fileName}),
cache: "no-cache",
credentials: "same-origin",
headers: {
"Content-Type": "application/json"
},
method: "POST",
mode: "cors"
});
const fileData = await fileResponse.json();
const aTag = document.createElement("a");
aTag.href = fileData.fileLink;
aTag.download = fileData.fileName;
aTag.click();
因此,服务器根本不需要处理文件,没有额外的 CPU、RAM 或流量影响,无论我尝试下载的文件有多大。