• vue3利用 a 标签,文件流,JSZip 压缩包,实现文件下载


    序:

    在实现文件的下载,采用 a 标签,会出现图片,没有进行下载,而是,在当前页面打开了图片。

    导致原因: ·a标签,有 download 属性,可以实现下载 同源文件( ip 和 端口 相同),当图片不同源 时,点击下载,会在当前窗口直接打开图片,而不是进入下载状态。

    1. 后端返回文件 url (a标签)

    1.1 没有图片的情况

    <template>
      <div>
        <a-modal v-model:visible="props.visible"  title="DownloadFile">
        <div class="down-load-file" v-for = "(item, index) in fileList" :key="index">
          <h4>{{item.fileType}}: h4>
          <a :href="item.fileUrl" download>{{item.fileName}}a>
        div>
        a-modal>
      div>
    template>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    1.2 下载远程图片

    1.2.1 图片地址后加"?response-content-type=application/octet-stream"

    使用contentType访问页面的时候,浏览器就会开启下载框对其内容进行下载

    <template>
      <div>
        <a-modal v-model:visible="props.visible"  title="DownloadFile">
        <div class="down-load-file" v-for = "(item, index) in fileList" :key="index">
          <h4>{{item.fileType}}: h4>
          <span class="opr-btn-normal" @click="download(item.fileUrl)">{{item.fileName}}span>
        div>
        a-modal>
      div>
    template>
    <script lang="ts" setup>
    import { onMounted, createVNode, reactive, defineComponent, ref } from 'vue';
    
    // 列表
    const fileList = ref<any[]>([]);
    
    const download = (url) => {
      // 处理图片下载
      let newstring= url.substring(url.length-4, url.length);
      if(['.png', '.jpg','jpeg', '.bmp', '.gif', 'webp', '.psd', '.svg', 'tiff'].indexOf(newstring) !== -1) {
        url = url + '?response-content-type=application/octet-stream'
      }
      let a = document.createElement("a");
        a.setAttribute("href", url);
        a.setAttribute("download",'');
        a.setAttribute("target", "_blank");
        let clickEvent = document.createEvent("MouseEvents");
        clickEvent.initEvent("click", true, true);
        a.dispatchEvent(clickEvent);
    }
    
    script>
    
    <style lang="less">
    .opr-btn-normal {
      color: #007df1;
      cursor: pointer;
      &:hover {
        text-decoration: underline;
      }
    }
    .down-load-file {
      display: flex;
      >span {
        margin-left: 10px;
      }
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    1.2.2、通过 canvas 方式 保存图片
    <script>
      /**
       * 下载图片
       * @param {string} imgsrc 图片地址
       */
      downloadIamge(imgsrc) {
        // 新建图片对象
        let image = new Image();
        // 解决跨域 Canvas 污染问题
        image.setAttribute("crossOrigin", "anonymous");
        // 图片加载
        image.onload = function() {
          // 新建 canvas标签
          let canvas = document.createElement("canvas");
          // 设置 canvas宽高
          canvas.width = image.width;
          canvas.height = image.height;
          // 添加 canvas画笔
          let context = canvas.getContext("2d");
          // 绘制图片
          context.drawImage(image, 0, 0, image.width, image.height);
          // 得到图片的 base64 编码
          let url = canvas.toDataURL("image/png");
          // 新建 a标签
          let a = document.createElement("a");
          // 新建点击事件
          let event = new MouseEvent("click");
          // 将图片的 base64 编码,设置为 a标签的地址
          a.href = url;
          // 触发点击事件
          a.dispatchEvent(event);
        };
        // 将图片地址 设置为 传入的参数 imgsrc
        image.src = imgsrc;
      };
     
      /**
       * 下载方法
       * @param {string} filepath 文件地址
       */
      downloads(filepath) {
        // isImageFile():自定义函数,根据*后缀*判断是否是图片
        if (isImageFile(filepath)){
          this.downloadIamge(filepath)
        } else {
          this.downloadFile(filepath)
        }
      };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49

    2. 后台返回文件流时,用 blob 对象下载文件

    参考

    // res 是返回的文件流,type 是文件MIME类型, fileName 是给下载的文件一个名称
    const blobDownloadFile = (res: any, type: string, fileName: string) => {
      const blob = new Blob([res], {
        type: type
      })
      const a = document.createElement('a')
      const URL = window.URL || window.webkitURL
      const herf = URL.createObjectURL(blob)
      a.href = herf
      a.download = fileName
      document.body.appendChild(a)
      a.click()
      document.body.removeChild(a)
      window.URL.revokeObjectURL(herf)
    }
    blobDownloadFile(url, 'text/plain', '测试')
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    3. JSZip 库以压缩包下载文件

    JSZip库
    组件中使用

    import { onMounted } from 'vue'
    import JSZip from 'jszip'
    import JSZipUtils from 'jszip-utils'
    import { saveAs } from 'file-saver'
    
    let dowloadZip: JSZip
    const urlToPromise = (url: string) =>
      new Promise((resolve, reject) => {
        JSZipUtils.getBinaryContent(url, (err: any, data: unknown) => {
          if (err) {
            reject(err)
          } else {
            resolve(data)
          }
        })
      })
    
    // 添加文件
    dowloadZip.file(item.fileName, urlToPromise(item.fileUrl), { binary: true })
    
    // .generateAsync() 生成一个 zip 文件
    dowloadZip
      .generateAsync({ type: 'blob' })
      .then(
        (blob) => {
          // saveAs(blob, "测试.zip"); 直接在浏览器打成 测试.zip 包并下载
          saveAs(blob, '测试.zip')
        },
        (e) => {
          console.log(e)
        }
      )
    
    // 在 DOM 挂载之后创建 JSZip 实例
    onMounted(() => {
      dowloadZip = new JSZip()
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
  • 相关阅读:
    云计算、区块链、大数据之间的关系与特点
    计算机毕业设计选题推荐-记录生活微信小程序/安卓APP-项目实战
    vue2vue3生命周期详解
    【牛客 - 剑指offer】JZ21 调整数组顺序使奇数位于偶数前面(一) 三种方案 Java实现
    docker安装使用xdebug
    wxpython使用中出现的内存泄露问题
    038-JTable控件应用案例讲解
    【翻译】Diversified Arbitrary Style Transfer via Deep Feature Perturbation
    【正点原子i.MX93开发板试用连载体验】简单的音频分类
    【广州华锐互动】利用VR开展细胞基础实验教学有什么好处?
  • 原文地址:https://blog.csdn.net/MoXinXueWEB/article/details/126747484