axios分段下载文件

5 篇文章 0 订阅
2 篇文章 0 订阅

之前遇到一个文件过大下载链接断开的问题,刚开始增加超时时间,效果并不好,后来经过各方面研究,上传都可以分段上传,下载也可以,所以和后端配合,实现了分段下载功能,现在把axios如何实现分段下载逻辑,总结成方法,以便以后参考。

<template></template>

<script>
export default {
  name: "download",
  data() {
    return {
      percentage: -1, // 下载进度
    };
  },
  methods: {
    // 分段下载需要后端配合
    download() {
      // 下载地址
      const url = "...";
      const chunkSize = 1024 * 1024 * 100; // 单个分段大小,这里测试用100M
      let filesTotalSize = chunkSize; // 安装包总大小,默认100M
      let filesPages = 1; // 总共分几段下载
      let filesCurrentPage = 0; // 第几段
      let contentList = []; // 文件流数组
      let sentAxios = (num) => {
        let rande = chunkSize;
        if (num) {
          rande = `${(num - 1) * chunkSize + 2}-${num * chunkSize + 1}`;
        } else {
          // 第一次0-1方便获取总数,计算下载进度,每段下载字节范围区间
          rande = "0-1";
        }
        let headers = {
          range: rande,
        };
        this.axios({
          method: "get",
          url: url,
          data: {},
          headers: headers,
          responseType: "blob",
          onDownloadProgress: (a) => {
            if (!num) {
              return;
            }
            var percent = parseInt(
              100 * ((a.loaded + 2 + (num - 1) * chunkSize) / filesTotalSize)
            );
            this.$nextTick(() => {
              this.percentage = percent;
              if (percent == 100) {
                // 1秒后隐藏进度显示
                setTimeout(() => {
                  this.percentage = -1;
                }, 1000);
              }
            });
          },
        })
          .then((response) => {
            if (response.status == 200 || response.status == 206) {
              //检查了下才发现,后端对文件流做了一层封装,所以将content指向response.data即可
              const content = response.data;
              // 获取文件总大小,方便计算下载百分比
              filesTotalSize = response.headers["content-range"].split("/")[1];
              // 计算总共页数,向上取整
              filesPages = Math.ceil(filesTotalSize / chunkSize);
              contentList.push(content); // 文件流数组
              // 递归获取文件数据
              if (filesCurrentPage < filesPages) {
                filesCurrentPage++;
                sentAxios(filesCurrentPage);
                return;
              }
              //构造一个blob对象来处理数据
              const reader = new FileReader();
              reader.readAsText(response.data);
              reader.onload = () => {
                try {
                  // 如果返回的报文不是数据流,而是json,比如登录失效,执行下面逻辑
                  const res = JSON.parse(reader.result);
                  if (res.code === 401) {
                    // ...处理逻辑
                  }
                } catch (err) {
                  const blob = new Blob(contentList);
                  // 文件名称
                  const fileName = response.fname;
    
                  //对于<a>标签,只有 Firefox 和 Chrome(内核) 支持 download 属性
                  //IE10以上支持blob但是依然不支持download
                  if ("download" in document.createElement("a")) {
                    //支持a标签download的浏览器
                    const link = document.createElement("a"); //创建a标签
                    link.download = fileName; //a标签添加属性
                    link.style.display = "none";
                    link.href = URL.createObjectURL(blob);
                    document.body.appendChild(link);
                    link.click(); //执行下载
                    URL.revokeObjectURL(link.href); //释放url
                    document.body.removeChild(link); //释放标签
                  } else {
                    //其他浏览器
                    navigator.msSaveBlob(blob, fileName);
                  }
                  this.$message.success("下载完成!");
                }
              }
            } else {
              this.$message.error("下载失败!");
            }
          })
          .catch(function (error) {
            console.log(error);
          });
      };
      // 第一次获取数据方便获取总数
      sentAxios(filesCurrentPage);
    },
  },
};
</script>

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Vue axios分段上传可以通过将文件分割成多个块,并使用axios的post方法逐个上传这些块来实现。可以使用FormData对象来创建一个包含文件块的表单数据,并在每个请求中设置适当的请求头。 首先,需要将文件分割成块。可以使用File API的slice方法来实现这一点。根据文件的大小和每个块的大小,可以计算出需要分割的块数。 然后,可以创建一个循环来逐个上传这些块。在每次循环迭代中,创建一个新的FormData对象,并向其中添加当前块。还需要设置适当的请求头,以便服务器能够正确地识别和重组这些块。 最后,可以使用axios的post方法将每个块上传到服务器。在每个请求的回调函数中,可以检查上传的进度,并根据需要更新UI。 如下是一个示例代码: ```javascript import axios from 'axios'; const CHUNK_SIZE = 1024 * 1024; // 每个块的大小,这里设置为1MB function uploadFile(file) { const fileSize = file.size; const totalChunks = Math.ceil(fileSize / CHUNK_SIZE); for (let i = 0; i < totalChunks; i++) { const start = i * CHUNK_SIZE; const end = start + CHUNK_SIZE; const chunk = file.slice(start, end); const formData = new FormData(); formData.append('file', chunk, file.name); formData.append('chunkIndex', i); formData.append('totalChunks', totalChunks); axios.post('/upload', formData, { headers: { 'Content-Type': 'multipart/form-data', }, onUploadProgress: (progressEvent) => { const progress = Math.round((progressEvent.loaded / progressEvent.total) * 100); console.log(`Chunk ${i + 1}/${totalChunks} uploaded: ${progress}%`); }, }); } } // 使用示例 const fileInput = document.getElementById('fileInput'); fileInput.addEventListener('change', (event) => { const file = event.target.files[0]; uploadFile(file); }); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小小•愿望

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值