如何使用Node.js从Dropbox下载大文件?

4

我想要实现一个大文件下载(大约10-1024 MB)。我已经成功从Dropbox获取了一个文件:

operationResult = await dbx.filesDownload({
    path: `/${CONFIG_STORAGE.uploader.assetsPath}/${fileUUID}`
});

然后我将接收到的文件与元数据绑定,并将其返回给我的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();

但我总是遇到“失败-没有文件”的错误。我也尝试使用jQuery AJAX和XMLHttpRequest(XHR),但仍然没有下载任何文件。

也许我错过了什么。如何从服务器获取10-1024 Mb的文件?

P.S. 我从未想过像文件下载这样的琐事会如此复杂。

1个回答

4

通过从filesDownload切换到filesGetTemporaryLink解决了这个问题,后者返回一个文件的链接而不是文件本身。然后我触发了对此链接的下载。

最终结果:

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或流量影响。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接