美文网首页React
自定义 hook —— useDownload

自定义 hook —— useDownload

作者: Lia代码猪崽 | 来源:发表于2021-11-02 15:36 被阅读0次

    基础功能

    1. 根据单个链接下载文件到本地
    2. 根据多个链接同时下载文件到本地
    3. 下载中的状态 state

    具体实现代码

    import { useState } from 'react'
    import { message, Modal } from 'antd'
    
    // urlPrefix 下载链接的前缀,如 window.location.host 等
    const useDownLoad = (urlPrefix = '') => {
      // 批量下载按钮用到的 loading 状态
      const [downloadLoading, setDownloadLoading] = useState(false)
    
      // 使用 iframe 的方法下载,window.open 或 a 标签 download 属性会拦截多次下载
      const createIFrame = (
        url,
        triggerDelay,  
        removeDelay,
        isEnd,
        isBatchDownload
      ) => {
        // 动态添加 iframe ,设置 src ,然后删除
        setTimeout(() => {
          var frame = document.createElement('iframe')
          frame.src = url  // 去加载,才会下载
          frame.style.display = 'none'  // 用户无感的关键,不展示
          document.body.appendChild(frame)  // 直接加到 body 底部
          // 关闭 loading 状态和 iframe 的延迟回调
          setTimeout(function() {
            if (isEnd && isBatchDownload) {  // 结束后关闭批量的 loading 状态
              setDownloadLoading(false)
            }
            frame.remove()
          }, removeDelay)
        }, triggerDelay)
      }
    }
    
      // 统一封装的下载函数,voiceUrlArray 为下载的 url 数组,isBatchDownload 为是否批量下载
      const download = (voiceUrlArray, isBatchDownload) => {
        if (voiceUrlArray?.length === 0) {
          message.error('下载失败')
          return
        }
        if (isBatchDownload) {
          setDownloadLoading(true)
        }
        let triggerDelay = 100  // 切换下载下一个文件的间隔时间
        let removeDelay = 2000  // 打开 iframe 到关闭 iframe 的间隔时间
        // 遍历 url 数组,开始下载
        voiceUrlArray.forEach((item, index) => {
          createIFrame(
            urlPrefix + item,  // 下载 url
            index * triggerDelay,  // 按顺序排队队打开,所以要用到 index
            removeDelay,  // 打开 iframe 到关闭 iframe 的间隔时间
            index === voiceUrlArray.length - 1,  // 是否是最后一个
            isBatchDownload  // 是否批量下载,如果还已经是最后一个要关闭 loading 状态的
          )
        })
      }
    
      // 会 return 出去的下载单个文件的方法
      const handleDownload = voiceUrl => {
        if (!voiceUrl) {
          message.error('下载失败')
          return
        }
        // 包装成数组,复用 download 方法
        download([voiceUrl], false)
      }
    
      // 会 return 出去的批量下载多个文件的方法
      const handleBatchDownload = (selectedRows, voiceUrlKey = '') => {
        if (selectedRows.length <= 0) {
          Modal.info({
            title: '提示',
            content: '请先选择文件',
            onOk() {}
          })
          return
        }
        let arr = []
        selectedRows.forEach(item => {
          // selectedRows 可能为对象数组,也可能为字符串数组
          arr = [...arr, ...([voiceUrlKey ? item[voiceUrlKey] : item] || [])]
        })
        download(arr)
      }
    
     return {
        downloadLoading,
        handleDownload,
        handleBatchDownload
      }
    }
    
    export default useDownLoad
    
    

    相关文章

      网友评论

        本文标题:自定义 hook —— useDownload

        本文链接:https://www.haomeiwen.com/subject/gzoxzltx.html