美文网首页js css html
3种前端文件下载的方式

3种前端文件下载的方式

作者: mudssky | 来源:发表于2022-12-05 15:17 被阅读0次

    前端下载有两种,一种是直接让浏览器接管的(点击a链接触发),另一种是先在内存里下载好(blob),然后调用浏览器的保存。

    1.window.open

    我最初使用的方法就是这个,只要提供了文件的服务器地址,使用window.open也就是在新窗口打开,这时浏览器会自动执行下载。

    2.a标签

    其实window.open和a标签是一样的,只是a标签是要用户点击触发,而window.open可以主动触发

    后端如果设置了Content-Disposition ,那么不需要download属性也能下载。而且后端还可以设置文件名。

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

    3.xhr(axios)下载

    这个时候,请求发送的时候需要注明responseType = "blob",如果没有设置的情况下,new Blob的时候需要传入第二个参数。比如new Blob([res], { type: xhr.getResponseHeader("Content-Type") });

    只是这时后端就没法通过body报错了。只能通过状态码和响应头来传递信息了。

    最后我还是选择用json来传递信息,设置这个responseType: 'blob',以后,返回值会被转为blob,这时我们log可以看到type,是application/json的情况就是报错的情形。然后我们转化一遍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框架

    返回文件流调用c.File,文件类型不用传,c.Header("Content-Disposition", "attachment; filename="+req.Name)这个设置可以返回文件名。

    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转换为url,然后绑到a链接上,通过点击a链接的方式触发下载。

    /**
     * 使用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对象
    }
    
    

    相关文章

      网友评论

        本文标题:3种前端文件下载的方式

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