自定義 hook —— useDownload

基礎(chǔ)功能

  1. 根據(jù)單個鏈接下載文件到本地
  2. 根據(jù)多個鏈接同時下載文件到本地
  3. 下載中的狀態(tài) state

具體實(shí)現(xiàn)代碼

import { useState } from 'react'
import { message, Modal } from 'antd'

// urlPrefix 下載鏈接的前綴,如 window.location.host 等
const useDownLoad = (urlPrefix = '') => {
  // 批量下載按鈕用到的 loading 狀態(tài)
  const [downloadLoading, setDownloadLoading] = useState(false)

  // 使用 iframe 的方法下載,window.open 或 a 標(biāo)簽 download 屬性會攔截多次下載
  const createIFrame = (
    url,
    triggerDelay,  
    removeDelay,
    isEnd,
    isBatchDownload
  ) => {
    // 動態(tài)添加 iframe ,設(shè)置 src ,然后刪除
    setTimeout(() => {
      var frame = document.createElement('iframe')
      frame.src = url  // 去加載,才會下載
      frame.style.display = 'none'  // 用戶無感的關(guān)鍵,不展示
      document.body.appendChild(frame)  // 直接加到 body 底部
      // 關(guān)閉 loading 狀態(tài)和 iframe 的延遲回調(diào)
      setTimeout(function() {
        if (isEnd && isBatchDownload) {  // 結(jié)束后關(guān)閉批量的 loading 狀態(tài)
          setDownloadLoading(false)
        }
        frame.remove()
      }, removeDelay)
    }, triggerDelay)
  }
}

  // 統(tǒng)一封裝的下載函數(shù),voiceUrlArray 為下載的 url 數(shù)組,isBatchDownload 為是否批量下載
  const download = (voiceUrlArray, isBatchDownload) => {
    if (voiceUrlArray?.length === 0) {
      message.error('下載失敗')
      return
    }
    if (isBatchDownload) {
      setDownloadLoading(true)
    }
    let triggerDelay = 100  // 切換下載下一個文件的間隔時間
    let removeDelay = 2000  // 打開 iframe 到關(guān)閉 iframe 的間隔時間
    // 遍歷 url 數(shù)組,開始下載
    voiceUrlArray.forEach((item, index) => {
      createIFrame(
        urlPrefix + item,  // 下載 url
        index * triggerDelay,  // 按順序排隊隊打開,所以要用到 index
        removeDelay,  // 打開 iframe 到關(guān)閉 iframe 的間隔時間
        index === voiceUrlArray.length - 1,  // 是否是最后一個
        isBatchDownload  // 是否批量下載,如果還已經(jīng)是最后一個要關(guān)閉 loading 狀態(tài)的
      )
    })
  }

  // 會 return 出去的下載單個文件的方法
  const handleDownload = voiceUrl => {
    if (!voiceUrl) {
      message.error('下載失敗')
      return
    }
    // 包裝成數(shù)組,復(fù)用 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 可能為對象數(shù)組,也可能為字符串?dāng)?shù)組
      arr = [...arr, ...([voiceUrlKey ? item[voiceUrlKey] : item] || [])]
    })
    download(arr)
  }

 return {
    downloadLoading,
    handleDownload,
    handleBatchDownload
  }
}

export default useDownLoad

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容