公共Hooks封装文件下载useDownloadFile实例详解

 更新时间:2022年11月25日 15:00:05   作者:JasonSubmara  
这篇文章主要为大家介绍了公共Hooks封装文件下载useDownloadFile实例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

引言

对于经常需要开发企业管理后台的前端开发来说,必不可少的需要使用表格对于数据进行操作,在对于现有项目进行代码优化时,封装一些公共的Hooks.

本篇文章为useDownloadFile.js

基于个人项目环境进行封装的Hooks,仅以本文介绍封装Hooks思想心得,故相关代码可能不适用他人

项目环境

Vue3.x + Ant Design Vue3.x + Vite3.x

对于企业管理后台中常见的各类资源文件(图片、文档、音视频等),下载保存本地则是再正常不过的需求了,为保证统一性和避免每个单页面文件内重复书写冗余代码,封装此方法

封装前提:各方法对比

方法操作原理优点缺点
form 表单动态生成一个表单,利用表单提交的功能来实现文件的下载兼容性好,不会出现URL长度限制问题无法知道下载的进度,用户体验交互差
无法直接下载浏览器可直接预览的文件类型
window.open / location.href打开新标签页访问下载资源简单粗暴会出现URL长度限制问题
无法知道下载的进度,用户体验交互差
无法直接下载浏览器可直接预览的文件类型
需要注意url编码问题
不能添加header,也就不能进行鉴权
<a /> download 属性利用a标签原生访问属性,附加新增的download属性,使用浏览器进行下载简单粗暴且可下载正常预览文件不能下载跨域地址文件
IE/Edge内兼容问题
无法鉴权
Blob 对象发请求获取二进制数据,转化为Blob对象,利用URL.createObjectUrl生成url地址,赋值在a标签的href属性上,结合download进行下载能解决不能直接下载浏览器可浏览的文件
可以鉴权
IE10以下不可用
Safari使用情况可能有问题

综上并结合实际项目,最后使用Blob对象进行封装下载文件方法

封装分解:下载核心代码

xhr.onloadend = function (e) {
  if (e.target.status === 200 || e.target.status === 304) {
    const aElement = document.createElement('a');
    const blob = e.target.response;
    const url = window.URL.createObjectURL(blob);
    aElement.style.display = 'none';
    aElement.href = url;
    aElement.download = `${options.fileName}.${fileType}`;
    document.body.appendChild(aElement);
    aElement.click();
    if (window.URL) {
      window.URL.revokeObjectURL(blob);
    } else {
      window.webkitURL.revokeObjectURL(blob);
    }
    document.body.removeChild(aElement);
  }
};
xhr.send();

封装分解:用户体验设计

  • 下载过程中,配合项目使用的Ant Design Vue框架,可以加强用户感知文件下载进度,
  • 为防止用户暴力点击,重复触发下载的问题,使用Loading Flag标识,
  • 下载失败后,提示用户,重新下载
createVNode('div', {}, ['文件下载过程中请勿关闭当前页面']),
createVNode('div', { className: 'mt-2' }, [`当前下载进度 ${progress.value}%`]),
catch (e) {
  console.error(e);
  downloading = false;
  infoModal && infoModal.destroy();
  Modal.error({
    title: '提示',
    content: '下载发生异常,请重试',
  });
}

useDownloadFile.js完整代码

import { createVNode, ref, onBeforeUnmount } from 'vue';
import { Modal } from 'ant-design-vue';
export function useDownloadFile() {
  let xhr = null;
  let downloading = false; // 限制同一文件同时触发多次下载
  let infoModal;
  onBeforeUnmount(() => {
    xhr && xhr.abort();
  });
  const downloadFile = options => {
    try {
      if (downloading || !options.url || !options.fileName) return;
      downloading = true;
      options.url = options.url.replace('http://', 'https://');
      const progress = ref(0);
      const fileType = options.url.split('.').pop();
      xhr = new XMLHttpRequest();
      xhr.responseType = 'blob';
      xhr.open('get', options.url, true);
      infoModal = Modal.info({
        title: '文件下载',
        okText: '取消下载',
        content: () => {
          return createVNode('div', {}, [
            createVNode('div', {}, ['文件下载过程中请勿关闭当前页面']),
            createVNode('div', { className: 'mt-2' }, [`当前下载进度 ${progress.value}%`]),
          ]);
        },
        onOk() {
          xhr.abort();
          return Promise.resolve();
        },
      });
      xhr.onprogress = function (e) {
        progress.value = Math.floor((e.loaded / e.total) * 100);
        if (progress.value === 100) {
          downloading = false;
          infoModal.destroy();
        }
      };
      xhr.onloadend = function (e) {
        if (e.target.status === 200 || e.target.status === 304) {
          const aElement = document.createElement('a');
          const blob = e.target.response;
          const url = window.URL.createObjectURL(blob);
          aElement.style.display = 'none';
          aElement.href = url;
          aElement.download = `${options.fileName}.${fileType}`;
          document.body.appendChild(aElement);
          aElement.click();
          if (window.URL) {
           window.URL.revokeObjectURL(blob);
          } else {
            window.webkitURL.revokeObjectURL(blob);
          }
          document.body.removeChild(aElement);
        }
      };
      xhr.send();
    } catch (e) {
      console.error(e);
      downloading = false;
      infoModal && infoModal.destroy();
      Modal.error({
        title: '提示',
        content: '下载发生异常,请重试',
      });
    }
  };
  return {
    downloadFile,
  };
}

以上就是公共Hooks封装文件下载useDownloadFile实例详解的详细内容,更多关于公共Hooks封装文件下载的资料请关注脚本之家其它相关文章!

相关文章

  • vue使用websocket的方法实例分析

    vue使用websocket的方法实例分析

    这篇文章主要介绍了vue使用websocket的方法,结合实例形式对比分析了vue.js使用websocket的相关操作技巧与注意事项,需要的朋友可以参考下
    2019-06-06
  • vue3中vue-meta的使用方法解析

    vue3中vue-meta的使用方法解析

    这篇文章主要介绍了vue3中vue-meta的使用方法,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • vue.js指令v-model实现方法

    vue.js指令v-model实现方法

    这篇文章主要为大家详细介绍了vue.js指令v-model实现方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2016-12-12
  • vue项目开发环境工具node搭建过程

    vue项目开发环境工具node搭建过程

    最近在开始接触做vue框架的前端项目,以前用的前端比如html,js,css等都是比较原生的,写好后直接浏览器打开就行,今天就先记录一下vue的开发运行搭建过程,感兴趣的朋友一起看看吧
    2023-09-09
  • Vue.js列表渲染绑定jQuery插件的正确姿势

    Vue.js列表渲染绑定jQuery插件的正确姿势

    这篇文章主要为大家详细介绍了Vue.js列表渲染绑定jQuery插件的正确姿势,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-06-06
  • 解决Vue打包上线之后部分CSS不生效的问题

    解决Vue打包上线之后部分CSS不生效的问题

    今天小编就为大家分享一篇解决Vue打包上线之后部分CSS不生效的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-11-11
  • vue项目在IE浏览器下运行空白问题及解决

    vue项目在IE浏览器下运行空白问题及解决

    IE11浏览器无法解析ES6语法导致Vue项目在IE11下显示空白,解决方法包括安装babel-polyfill,并在项目的main.js文件中引入babel-polyfill,此外,js-base64版本3及以上不兼容IE11,解决办法是使用版本3以下的js-base64,这些措施可以帮助兼容IE11,确保项目正常运行
    2024-09-09
  • vue项目根据不同环境进行设置打包命令的方法

    vue项目根据不同环境进行设置打包命令的方法

    这篇文章主要介绍了vue项目根据不同环境进行设置打包命令,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-11-11
  • vue2和vue3实现图片懒加载方式

    vue2和vue3实现图片懒加载方式

    这篇文章主要介绍了vue2和vue3实现图片懒加载方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-04-04
  • vue2之响应式双向绑定,在对象或数组新增属性页面无响应的情况

    vue2之响应式双向绑定,在对象或数组新增属性页面无响应的情况

    这篇文章主要介绍了vue2之响应式双向绑定,在对象或数组新增属性页面无响应的情况及解决,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-04-04

最新评论