使用streamsaver+fetch下载文件

问题

之前使用axios进行流处理文件下载的过程中,遇到大文件的话,axios就需要等待整个文件流都下载到内存中才会弹出浏览器的下载文件保存对话框,这种方式在下载小文件的场景没什么问题,但是遇到大文件,一方面是浏览器的下载保存对话框半天都不会响应客户,这样体验不是很好;另外一方面是受到客户端内存的限制。

解决

使用StreamSaver.js+fetch解决这个问题,fetch比axios区别在于只要响应马上就可以开始弹出浏览器下载保存对话框,并且不影响文件流下载,而axios非要等到整个文件流下完了才有响应。所以axios比较适合restful接口调用这种场景。

步骤

npm

npm install streamsaver

vue

const streamSaver = require('streamsaver');
...
const url = '/api/common/downloadFile?xxxx.srt'

      fetch(url, {
        method: 'GET',
        cache: 'no-cache',
        headers: {
          'xxxx': 'xxxx'
        }
      }).then(res => {

        const fileStream = streamSaver.createWriteStream('xxxx.srt', {
          size : res.headers.get("content-length")
        })

        const readableStream = res.body

        // more optimized
        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()
      })

总结

Fetch也是原生Javascript的API,是XHR的替代者。这里主要就是文件流下载并保存到本地。

参考:

  • StreamSaver.js
  • Piping a fetch response to StreamSaver

你可能感兴趣的:(使用streamsaver+fetch下载文件)