如何在浏览器上下载从 fetch 返回的 ReadableStream
我正在接收来自服务器的 ReadableStream,它是从我的 fetch 调用返回的.
I am receiving a ReadableStream from a server, returned from my fetch call.
返回了 ReadableStream,但我不知道如何从这个阶段触发下载.我不能在 href 中使用 url,因为它需要授权令牌.
A ReadableStream is returned but I don't know how to trigger a download from this stage. I can't use the url in an href because it requires an Authorization token.
我不想在客户端安装 fs
那么我有什么选择?
I don't want to install fs
on the client so what options do I have?
try {
const res = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`,
'Content-Type': 'application/octet-stream'
}
});
const blob = await res.blob();
const newBlob = new Blob([blob]);
const newUrl = window.URL.createObjectURL(newBlob);
const link = document.createElement('a');
link.href = newUrl;
link.setAttribute('download', 'filename');
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
window.URL.revokeObjectURL(newBlob);
} catch (error) {
console.log(error);
}
更新 1
我将文件转换为 Blob,然后将其传递给新生成的 href.成功下载了一个文件.最终结果是 ReadStream 内容为 .txt 文件.
I converted the file to a Blob, then passed it into a newly generated href. Successfully downloaded a file. The end result was the ReadStream contents as a .txt file.
意思是这样的
x:ÚêÒÓ%¶âÜTb∞܃
推荐答案
我找到了 2 个解决方案,两者都有效,但我缺少一个简单的补充来使它们有效.
I have found 2 solutions, both worked but I was missing a simple addition to make them work.
原生解决方案是
try {
const res = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`
}
});
const blob = await res.blob();
const newBlob = new Blob([blob]);
const blobUrl = window.URL.createObjectURL(newBlob);
const link = document.createElement('a');
link.href = blobUrl;
link.setAttribute('download', `${filename}.${extension}`);
document.body.appendChild(link);
link.click();
link.parentNode.removeChild(link);
// clean up Url
window.URL.revokeObjectURL(blobUrl);
此版本正在使用 npm 包 steamSaver 供任何喜欢它的人使用.
This version is using the npm package steamSaver for anyone who would prefer it.
try {
const res = await fetch(url, {
method: 'GET',
headers: {
Authorization: `Bearer ${token}`
}
});
const fileStream = streamSaver.createWriteStream(`${filename}.${extension}`);
const writer = fileStream.getWriter();
const reader = res.body.getReader();
const pump = () => reader.read()
.then(({ value, done }) => {
if (done) writer.close();
else {
writer.write(value);
return writer.ready.then(pump);
}
});
await pump()
.then(() => console.log('Closed the stream, Done writing'))
.catch(err => console.log(err));
它不起作用的关键是因为我没有包含扩展名,所以它要么因为 mimetype 错误而出错,要么它打开一个带有正文字符串而不是图像的 .txt 文件.
The key for why it was not working was because I did not include the extension, so it either errored out because of the mimetype was wrong or it opens a .txt file with a string of the body instead of the image.
相关文章