3種前端文件下載的方式

前端下載有兩類,一類是直接讓瀏覽器接管的(點擊a鏈接觸發(fā)),另一類是先在內(nèi)存里下載好(blob),然后調(diào)用瀏覽器的保存。

1.window.open

我最初使用的方法就是這個,只要提供了文件的服務(wù)器地址,使用window.open也就是在新窗口打開,這時瀏覽器會自動執(zhí)行下載。

2.a標簽

其實window.open和a標簽是一樣的,只是a標簽是要用戶點擊觸發(fā),而window.open可以主動觸發(fā)

后端如果設(shè)置了Content-Disposition ,那么不需要download屬性也能下載。而且后端還可以設(shè)置文件名。

<a href="https:xxx.mp4" download="test">下載文件</a>

3.xhr(axios)下載

這個時候,請求發(fā)送的時候需要注明responseType = "blob",如果沒有設(shè)置的情況下,new Blob的時候需要傳入第二個參數(shù)。比如new Blob([res], { type: xhr.getResponseHeader("Content-Type") });

只是這時后端就沒法通過body報錯了。只能通過狀態(tài)碼和響應(yīng)頭來傳遞信息了。

最后我還是選擇用json來傳遞信息,設(shè)置這個responseType: 'blob',以后,返回值會被轉(zhuǎn)為blob,這時我們log可以看到type,是application/json的情況就是報錯的情形。然后我們轉(zhuǎn)化一遍json可以拿到報錯信息,其實也可以把這個邏輯加到axios攔截器里面

export const DOWNLOAD_ITEM = async (data: FileItem): Promise<any> => {
  const res: Blob = await request.post(`${PROXY_SUFFIX}/downloadItem`, data, {
    responseType: 'blob',
  })
  // json的情況說明是報錯
  if (res.type !== 'application/json') {
    downloadFile(res, data.name)
  } else {
    const r = await res.text()
    message.error(JSON.parse(r)?.msg)
  }
}

這邊我后端用的是golang的gin框架

返回文件流調(diào)用c.File,文件類型不用傳,c.Header("Content-Disposition", "attachment; filename="+req.Name)這個設(shè)置可以返回文件名。

func (f *FileListAPI) DownloadItem(c *gin.Context) {
    var req response.FileInfo
    err := c.ShouldBindJSON(&req)
    if err != nil {
        response.FailWithMessage(err.Error(), c)
        return
    }
    if req.Path == "" {
        response.FailWithMessage("路徑不能為空", c)
        return
    }
    if req.IsFolder {
        response.FailWithMessage("路徑不能為文件夾", c)
        return
    } else {
        c.Header("Content-Disposition", "attachment; filename="+req.Name)
        // c.Header("Content-Transfer-Encoding", "binary")
        // c.Header("Content-Type", "application/octet-stream")
        c.File(req.Path)
    }
    fmt.Println("req", req)

}

下面是blob對象下載的邏輯,使用createObjectURL轉(zhuǎn)換為url,然后綁到a鏈接上,通過點擊a鏈接的方式觸發(fā)下載。

/**
 * 使用bolb方式下載
 * @param res
 * @param filename
 * @returns
 */
export function downloadFile(res: Blob, filename: string) {
  const url = window.URL.createObjectURL(new Blob([res]))
  const a = document.createElement('a')
  a.style.display = 'none'
  a.href = url
  a.download = filename
  document.body.appendChild(a)
  a.click()
  document.body.removeChild(a)
  window.URL.revokeObjectURL(url) // 釋放blob對象
}

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

相關(guān)閱讀更多精彩內(nèi)容

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