【问题标题】:How to download a ReadableStream on the browser that has been returned from fetch如何在浏览器上下载从 fetch 返回的 ReadableStream
【发布时间】:2020-09-17 16:48:42
【问题描述】:

我从服务器接收到一个 ReadableStream,它是我的 fetch 调用返回的。

返回了 ReadableStream,但我不知道如何从这个阶段触发下载。我不能在 href 中使用 url,因为它需要授权令牌。

我不想在客户端上安装fs,那么我有什么选择?

  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 文件。

意思是这样的

x:ÚêÒÓ%¶âÜTb∞\܃

【问题讨论】:

  • 这里有很多关于如何使用可读流的信息developer.mozilla.org/en-US/docs/Web/API/Streams_API/…
  • 例如你可以做stream.pipe(fs.createWriteStream('file.txt'));
  • 我需要在浏览器上安装fs 来执行第二条评论中真正不推荐的操作,你甚至需要安装一个奇怪的版本,比如 0.0.1-security根据我的记忆,让它发挥作用
  • 啊,您是在浏览器中执行此请求吗?并想触发它“下载文件”?

标签: javascript browser download fetch-api


【解决方案1】:

我找到了 2 个解决方案,两者都有效,但我缺少一个简单的补充来使它们有效。

原生解决方案是

  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 供任何喜欢它的人使用。

  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 文件。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-06-06
    • 2018-11-05
    • 1970-01-01
    • 2021-06-29
    • 1970-01-01
    • 1970-01-01
    • 2014-03-31
    相关资源
    最近更新 更多