我的前端(用vuejs编写)需要从服务器下载大文件(〜1GB,但可能会变大)。我目前的方法是使用 streamsaver 但是,尽管我在测试时下载文件时似乎可以正常工作 时似乎很难
在本地,在其他设备上测试它 必须在下载操作开始之前完成,这实际上不是我需要的解决方案。我希望能够同时启动下载。
const fileStream = streamSaver.createWriteStream(fileName);
const res = await fetch("gets/download-file?" + new URLSearchParams({
relPath: path.join(forPath, fileName)
}))
const readableStream = res.body
if (window.WritableStream && readableStream.pipeTo) {
return readableStream.pipeTo(fileStream)
.then(() => console.log('done writing'))
}
window.writer = fileStream.getWriter()
const reader = res.body.getReader()
const pump = () => reader.read()
.then(res => res.done
? window.writer.close()
: window.writer.write(res.value).then(pump))
pump()
我的服务器是用express.js编写的,我也尝试从服务器端流式传输数据,
router.get("/download-file", checkPath, async (req, res) => {
try {
const relativePath = req.query.relPath;
const fullPath = path.join(UPLOAD_FOLDER, relativePath);
console.log(green("Downloading: ", fullPath))
// res.sendFile(fullPath, (err) => {
// if (err) console.log(red(err))
// })
res.setHeader('Content-Type', 'application/octet-stream');
fs.createReadStream(fullPath).pipe(res);
} catch (err) {
console.log(red(err))
}
})
我已经看到和其他类似的答案,使用streamsaver-js”>流式大斑点文件,但它们似乎都有类似的缺陷,即必须完成fetch请求并等待直到那时等待下载之前,不是我想要的。
My frontend (written in VueJS) needs to download a large file from a server (~1GB but can get even larger). My current approach is using streamSaver however, although this seems to work fine when I download files while testing locally, it seems to struggle when testing it on other devices (android phone while pointing the server to 0.0.0.0)
Front end Code for downloading, I'm currently piping the fetch data to streamSaver, however from what I understand, the fetch request has to complete before the download action starts, which isn't really the solution I require. I want to be able to start the download simultaneously.
const fileStream = streamSaver.createWriteStream(fileName);
const res = await fetch("gets/download-file?" + new URLSearchParams({
relPath: path.join(forPath, fileName)
}))
const readableStream = res.body
if (window.WritableStream && readableStream.pipeTo) {
return readableStream.pipeTo(fileStream)
.then(() => console.log('done writing'))
}
window.writer = fileStream.getWriter()
const reader = res.body.getReader()
const pump = () => reader.read()
.then(res => res.done
? window.writer.close()
: window.writer.write(res.value).then(pump))
pump()
My server is written in express.js, and I have also tried streaming the data from the server side as well
router.get("/download-file", checkPath, async (req, res) => {
try {
const relativePath = req.query.relPath;
const fullPath = path.join(UPLOAD_FOLDER, relativePath);
console.log(green("Downloading: ", fullPath))
// res.sendFile(fullPath, (err) => {
// if (err) console.log(red(err))
// })
res.setHeader('Content-Type', 'application/octet-stream');
fs.createReadStream(fullPath).pipe(res);
} catch (err) {
console.log(red(err))
}
})
I have seen Stream large blob file using StreamSaver.js, and other similar answers but they all seem to have similar flaws of having to complete the fetch request and wait till then before streaming a download, which isn't what I'm looking for.
发布评论
评论(1)
我想出了如何做到这一点,所以我要回答我的问题。
基本上,您应该让浏览器处理下载,而不是使用fetch API并尝试使用JavaScript下载文件。您只需要从后端提供文件 - res..download或node中的sendfile,然后直接导航到文件(例如锚固标签的方式),
并根据要求添加示例。
因此,在您的客户端上,假设您有一个下载按钮下载一些文件路径,因此您将拥有看起来像该
客户端的
代码,为此,您的服务器必须在该特定位置上使用请求的文件,即
/download? pathName = $ {fullpath}
服务器 - express
main.ts
这是一条路线 - 下载.ts
I figured out how to do this so I'm answering my question.
Basically instead of using the fetch api and trying to use javascript to download a file, you should let the browser handle the download. You just need to serve the file from your backend - res.download or sendFile in node and then navigate to the file directly (like how an anchor tag would do it)
Adding an example as requested.
so on your client let's say you have a download button that downloads some file path, so you would have code that looks like this
Client
and for this your server would have to serve the requested file at that particular location i.e.
/download?pathname=${fullpath}
Server - express
main.ts
this is a route - download.ts