StreamSaver.js入门教程:优雅解决前端下载文件的难题

这篇具有很好参考价值的文章主要介绍了StreamSaver.js入门教程:优雅解决前端下载文件的难题。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

本文简介

点赞 + 关注 + 收藏 = 学会了


本文介绍一个能让前端优雅下载大文件的工具:StreamSaver.js

  • ⚡️ StreamSaver.js GitHub地址
  • ⚡️ 官方案例

StreamSaver.js 可用于实现在Web浏览器中直接将大文件流式传输到用户设备的功能。

传统的下载方式可能导致大文件的加载时间较长或造成内存占用过大的问题,使用 <a> 标签打开新页面下载文件,遇到 .txt 或者 .mp4 之类的文件可能就直接在页面展示了,不会触发下载功能。而 StreamSaver.js 则通过流式下载的方式解决了这些问题。

StreamSaver.js 将大文件拆分成小块,并在下载过程中逐块传输到硬盘,从而降低内存占用和提高下载速度。



环境准备

要学习 StreamSaver.js 首先要准备一份或者多份可下载的文件。

你可以使用网络上的文件资源,但这需要你自己去找。

你也可以在自己的电脑运行个服务,把文件资源丢进去即可。


如果你用脚手架创建项目,比如vue或者react之类的项目,也可以把文件放在静态资源目录里。

比如用 vite 创建一个 Vue 项目,然后在 public 目录下创建一个 test.txt 文件。项目运行起来,在浏览器访问 http://localhost:端口号/public/test.txt 就能查看到这个文件内容。



安装 StreamSaver.js

可以使用 CDN 或者 npm 安装 StreamSaver.js

本文使用 CDN 的方式讲解。


CDN

打开 StreamSaver.js的仓库。

StreamSaver.js入门教程:优雅解决前端下载文件的难题,前端

StreamSaver.js 文件下载到你项目里引入即可。

<script src="../StreamSaver.js"></script>

npm

⚡️StreamSaver npm地址


使用以下命令下载 StreamSaver 到项目里

npm i streamsaver

然后在要使用的地方引入即可。

import streamSaver from "streamsaver"


起步

起步阶段,我们先试试如何下载一个 .txt 文件。

如果我们要下载一些浏览器读不懂的文件,我们可以使用 <a>标签在新窗口打开链接,也可以使用 windows.open('url') 的方式打开新窗口进行下载。

但如果这个文件浏览器是读得懂的,比如 .txt 文件,那浏览器就不会执行下载,而是会直接在页面中把文件内容展示出来。

此时就可以使用 StreamSaver.js 来解决这个问题。

使用 StreamSaver.js 下载文件的大概流程是这样的(为了方便理解,我用一些不专业的术语进行描述):

  1. 创建一个文件,该文件支持写入操作。streamSaver.createWriteStream('文件名.后缀')
  2. 使用 fetch 方法访问文件的url,将内容一点点的放到 StreamSaver 创建的文件里。
  3. 监听文件内容是否读取完整,读取完就执行“保存并关闭文件”的操作。

根据上面的指引编写代码:

<!-- 下载按钮 -->
<button id="download">下载</button>

<!-- 引入StreamSaver.js -->
<script src="../StreamSaver.js"></script>
<script>
  // 监听按钮点击事件,点击就下载文件
  download.onclick = () => {
    // 【步骤1】创建一个文件,该文件支持写入操作
    const fileStream = streamSaver.createWriteStream('test.txt') // 这里传入的是下载后的文件名,这个名字可以自定义

    // 【步骤2】使用 fetch 方法访问文件的url,将内容一点点的放到 StreamSaver 创建的文件里
    fetch('http://localhost:9988/public/test.txt')
      .then(res => {
        const readableStream = res.body
        if (window.WritableStream && readableStream.pipeTo) {
          return readableStream.pipeTo(fileStream)
            .then(() => console.log('完成写入'))
        }

        // 【步骤3】监听文件内容是否读取完整,读取完就执行“保存并关闭文件”的操作。
        window.writer = fileStream.getWriter()
        const reader = res.body.getReader()
        const pump = () => reader.read()
          .then(res => res.done
            ? writer.close()
            : writer.write(res.value).then(pump)
          )
        pump()
      })
  }
</script>

大概就是这样子了。


🔔提示

如果遇到提示跨域的问题,可以配置 mitm 指向 mitm.html

mitm.htmlStreamSaver.js仓库 里可以获取到。

StreamSaver.js入门教程:优雅解决前端下载文件的难题,前端

可以把 mitm.html 放到你服务器再配置。

streamSaver.mitm = 'https://你的服务器地址/mitm.html'


打包下载 zip

如果想将多个文件打包成zip下载到本地,可以将 StreamSaver.jszip-stream.js 结合在一起使用。

zip-stream.jsStreamSaver.js 的仓库里有。

StreamSaver.js入门教程:优雅解决前端下载文件的难题,前端

zip-stream.js/examples 目录里。


使用 npm 安装 streamsaver 也能在 /examples 目录下找到 zip-stream.js,直接引入即可。

import 'node_modules/streamsaver/examples/zip-stream.js'

如果使用 CDN 的方式就直接用 <script src='zip-stream.js'></script> 引入即可。


打包zip下载的步骤:

  1. 创建下载后的文件名和文件格式。
  2. 使用 zip-stream 创建一个 ZIP 实例,用来不断接收要下载的文件。
  3. 所有文件下载完成就执行 close() 方法将所有文件真正打包成一个 zip

<button id="download">下载</button>

<script src="../StreamSaver.js"></script>
<script src="zip-stream.js"></script>
<script>

    // 要下载的文件地址列表
    let urls = [
        {
            fileName: 'test.txt',
            url: 'http://localhost:9988/public/test.txt',
        },
        {
            fileName: 'test.csv',
            url: 'http://localhost:9988/public/test.csv',
        }
    ]

    download.onclick = () => {
        // 【步骤1】
        const fileStream = streamSaver.createWriteStream('test.zip')

        // 【步骤2】
        const readableZipStream = new ZIP({
            async pull(ctrl) {
                for (let i = 0; i < urls.length; i++) {
                    const res = await fetch(urls[i].url)
                    const stream = () => res.body
                    const name = urls[i].fileName
                    ctrl.enqueue({ name, stream }) // 不断接收要下载的文件
                }

                // 【步骤3】
                ctrl.close()
            }
        })

        if (window.WritableStream && readableZipStream.pipeTo) {
            return readableZipStream.pipeTo(fileStream).then(
                () => console.log('下载完了')
            )
        }
    }

</script>

点击下载按钮后的效果:

StreamSaver.js入门教程:优雅解决前端下载文件的难题,前端

这个例子准备了 .csv.txt 文件。下载时会合并成 .zip,解压后能看到里面的所有文件都是正常能打开的 。



合成文件再下载

在这个例子中,我要将2个 .csv 文件合并成1个再下载。

我准备了两个 .csv 文件(test1.csv 和 test2.csv),它们的内容分别长这个样子。

StreamSaver.js入门教程:优雅解决前端下载文件的难题,前端

我要将它们合并成这样子:

StreamSaver.js入门教程:优雅解决前端下载文件的难题,前端


在合并文件之前我们首先要清楚这个文件的内容是如何组成的。

在 Excel 中打开 .csv 的每个单元格的内容转换成文本形式的话是用逗号分隔。

StreamSaver.js入门教程:优雅解决前端下载文件的难题,前端

如果要合并多个 .csv 文件,只需监听到每个 .csv 下载完成,然后再拼接一个 \n 换行,再下载下一个 .csv 文件即可。


整理一下就是以下几个步骤:

  1. 拿到一组下载地址,把它们转存到一个迭代器里。
  2. 递归执行迭代器,如果迭代器里还有内容,就使用 fetch 请求数据。
  3. 如果迭代器没内容了,使用 writer.close() 关闭文件写入。

该功能写成真正的代码如下所示:

<button id="download" οnclick="down()">下载</button>

<script src="../StreamSaver.js"></script>
<script>
  // 编码转换方法
  let encode = TextEncoder.prototype.encode.bind(new TextEncoder)

  // 准备好要下载的链接
  const urls = [
    'http://localhost:9988/public/test1.csv',
    'http://localhost:9988/public/test2.csv'
  ]

  // 迭代器数据
  let urlsIter = null

  // 写入方法放到全局中保存
  let writer = null

  // 下载按钮点击事件
  function down() {
    // 创建一个下载管道,并将下载后的文件命名为 newTest.csv
    const fileStream = streamSaver.createWriteStream('newTest.csv')
    // 创建写入方法
    writer = fileStream.getWriter()
    // 将要下载的链接转换成迭代器
    urlsIter = urls[Symbol.iterator]()

    // 开始执行循环下载
    forDown()
  }

  // 循环下载的方法
  async function forDown() {
    // 获取迭代器最新一条数据
    let urlIter = urlsIter.next()
    // 如果迭代器没数据,执行写入完成操作,并停止递归
    if (urlIter.done) {
      writer.close()
      return
    }

    // 迭代器有内容时执行请求操作
    await fetch(urlIter.value)
      .then(res => {
        // 通过请求文件url获取到的数据
        const readableStream = res.body
        if (window.WritableStream && readableStream.pipeTo) {
          const reader = readableStream.getReader()
          // 讲获取到的每一包写入文件里
          const pump = () => {
            return reader.read()
              .then(readRes => {
                if (readRes.done) { // 当前文件读取完成后执行
                  // 文件读取完成后换行
                  writer.write(encode('\n'))
                  // 执行请求下一个文件
                  forDown()
                } else { // 文件读取过程执行
                  // 一包包写入
                  writer.write(readRes.value)
                    .then(pump)
                }
            })
          }
          pump()
        }
      })
  }
</script>

这个案例稍微复杂一丢丢,建议跟着手敲一遍。



推荐阅读

除了本文所讲内容外,StreamSaver.js 的仓库还有好几个实用的例子,有需要的工友可以去看看。


👍《前端中文汉字转拼音》

👍《提升日期处理效率:day.js 实战经验分享》

👍《眨个眼就学会了Pixi.js》

👍《OpenLayers.js 入门教程:打造互动地图的入门指南》

👍《物理世界的互动之旅:Matter.js入门指南》

👍《p5.js 光速入门》


点赞 + 关注 + 收藏 = 学会了 代码仓库文章来源地址https://www.toymoban.com/news/detail-720284.html

到了这里,关于StreamSaver.js入门教程:优雅解决前端下载文件的难题的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 前端vue引入高德地图入门教程

    距离上一篇关于前端项目中使用高德地图的文章已经将近5年之久, 这是我的第一篇关于高德地图的文章 这期间前端技术日新月异,5年前JQuery还如日中天,如今已经销声匿迹,很少有公司招聘还在要求JQuery,更多的是Vue、React。 如今更多采用模块化开发,结合webpack、vite,我

    2024年02月11日
    浏览(54)
  • Shopify开发入门-前端保姆级教程

    本文旨在介绍Shopify开发入门、环境、配置等,帮助开发者配置环境、了解各个开发模式的区别及用途;已有Shopify开发经验者可退出,以免浪费你的宝贵时间。 本文5k字+,图片、链接、代码块较多,请耐心阅读~ 最近在调研Shopify开发,对其也有了一定的认识、了解;即将这些

    2024年02月16日
    浏览(40)
  • D3JS教程_编程入门自学教程_菜鸟教程-免费教程分享

    D3是Data-Driven Documents的缩写,D3.js是一个基于数据管理文档的资源JavaScript库。 D3 是最有效的数据可视化框架之一。它允许开发人员在 HTML、CSS 和 SVG 的帮助下在浏览器中创建动态的交互式数据可视化。数据可视化是将过滤后的数据以图片和图形的形式表现出来。 D3.js入门教程

    2024年02月14日
    浏览(37)
  • 跟着pink老师前端入门教程-day03

    6.1 表格的主要作用 主要用于 显示、展示数据 ,可以让数据显示的规整,可读性非常好,特别是后台展示数据时,能够熟练运用表格就显得很重要。 6.2 基本语法 6.3 表头单元格标签 一般表头单元格位于表格的 第一行或第一列 ,表头单元格里面的 文本内容加粗居中显示 ,突

    2024年01月18日
    浏览(45)
  • 跟着pink老师前端入门教程(JavaScript)-day02

    1、什么是变量 白话:变量就是一个装东西的盒子 通俗:变量是用于存储数据的‘ 容器 ’,通过 变量名 获取数据,甚至数据可以修改 注意: 变量不是数据本身,它们仅仅是一个用于存储数值的容器。可以理解为是一个个用来装东西的纸箱子。 2、变量在内存中的存储 本质

    2024年02月20日
    浏览(47)
  • Babylon.js入门教程:探索3D世界的新维度

    随着3D技术的不断发展,越来越多的开发者开始涉足3D领域。在这个领域中,Three.js和Babylon.js是最受欢迎的两个框架。本文将为大家介绍Babylon.js的入门教程,并与Three.js进行对比,探讨它们的优缺点。 一、Babylon.js简介 Babylon.js是一个基于WebGL的开源3D游戏引擎,它可以在浏览器

    2024年02月13日
    浏览(40)
  • ECMAScript6历史-前端开发+ECMAScript+基础语法+入门教程

    我们首先来看 ECMA 是什么。 ECMA ,读音类似“埃科妈”,是 欧洲计算机制造商协会 (European Computer Manufacturers Association)的简称,是一家国际性会员制度的信息和电信标准组织。1994年之后,由于组织的标准牵涉到很多其他国家,为了体现其国际性,更名为 Ecma 国际 (Ecma In

    2024年01月16日
    浏览(48)
  • 03.Three.js的入门教程(二)如何创建一个3D地球?

    前言:通过上节课 02.Three.js的入门课程(一),我们了解了Three.js的最小案例DEMO,熟悉了几个重要组成部分。这节课带领大家编写一个3D地球。 一、通过纹理图渲染一个地球 1.1. 创建一个纹理加载器对象TextureLoader,可以加载图片作为纹理贴图; 1.2.完整代码结构 二、小球标

    2024年02月04日
    浏览(68)
  • 全栈教程:Spring Boot 和 Vue.js 入门

    在本教程中,你将创建一个 CoffeeBot 应用程序。该应用程序就像机器人咖啡机的控制器。遗憾的是,它实际上不会为你提供咖啡,但它将演示大量有用的编程技术。该应用程序将有一个 Vue.js 客户端和一个 Spring Boot 资源服务器。它将使用 JHipster 进行引导,节省大量时间并演示

    2024年02月15日
    浏览(48)
  • 前端基础从头学——VsCode使用教程+html基础(入门篇)

    作者简介:hello!大家好,初学前端知识,请多多指教。 希望我的分享能够帮助到更多的人,如果觉得我的分享有帮助的话,请大家一键三连支持一下哦~ ———————————————————————————— 刚接触前端,零基础小白,从头开始学起,请大家多多指

    2024年01月18日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包