• 前端文件下载实现方案,Blob对象为你实现任意文件下载



    前言

    本文主要介绍了如何使用 Blob对象 在前端实现文件下载的功能。

    文中首先介绍了什么是 Blob对象,它表示一个二进制大型对象,可以用来表示文件或二进制数据。然后详细讲解了几种生成 Blob对象 的方式,以及如何通过 createObjectURL 方法生成一个对象 URL,设置到 a 标签href 属性实现文件下载。文末还提到了一些优化下载体验的方法,比如设置 download 属性、使用 click 方法触发下载等。

    掌握 Blob 的使用可以实现强大的前端文件下载、上传、二进制数据处理功能,是很重要的能力。本文内容通俗易懂,可以帮助读者快速理解 Blob 的用法。

    一、Blob是什么?

    Blob(Binary Large Object) 表示二进制类型的大对象,可以用来表示文件或二进制数据。在前端中,我们可以通过 Blob对象 生成一个文件对象,然后通过创建一个 a标签 实现文件下载。

    二、生成Blob对象

    可以通过以下几种方式生成一个 Blob对象:

    // 从字符串生成Blob对象
    const blob = new Blob(['hello world']) 
    
    // 从数组生成Blob对象
    const blob = new Blob([new Uint8Array([1,2,3])]) 
    
    // 从另一个blob生成
    const newBlob = blob.slice() 
    
    // 从canvas生成
    canvas.toBlob(callback)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    生成的 Blob对象 表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据处理

    三、请求处理

    1、请求封装

    fileRequest.ts 文件中

    import axios from 'axios'
    
    // 创建axios实例
    const fileRequest = axios.create({
      timeout: 30 * 1000, // 请求超时时间
      responseType: 'blob', // *重点*
      withCredentials: true
    })
    
    // request 拦截器
    fileRequest.interceptors.request.use(
    	// 省略若干
    )
    
    // response 拦截器
    fileRequest.interceptors.response.use(
    	// 省略若干
    )
    
    export default fileRequest
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    2、根据后端接口配置

    fileApi.ts 文件中

    import fileRequest from './utils/fileRequest'
    
    // 文件下载接口
    export function postFileDownloadUrl(data = {}) {
    	return fileRequest({
    		url: '后端url'method: 'POST',
    		data
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    四、工具函数

    我们封装一个 download 工具函数,用来处理后端返回的任意二进制文件下载

    file.ts 文件中

    import { ElMessage } from "element-plus";
    import { blobType } from './blobType'
    
    export function download(file: any, fileType: string, fileName?: string) {
      if (!fileName) {
        const timeStr = new Date().getTime()
        fileName = `${timeStr}`
      }
      const type = formatFileType(fileType)
      if (!type) return ElMessage.warning('暂不支持此格式!')
      const blob = new Blob([file], { type })
      const downloadElement = document.createElement('a')
      const href = window.URL.createObjectURL(blob) // 创建下载的链接
      downloadElement.href = href
      downloadElement.download = fileName // 下载后文件名
      document.body.appendChild(downloadElement)
      downloadElement.click() // 点击下载
      document.body.removeChild(downloadElement) // 下载完成移除元素
      window.URL.revokeObjectURL(href) // 释放掉blob对象
    }
    
    export function formatFileType(fileFormat: string) {
      return blobType[fileFormat]
    }
    
    export function blobToFileReader(blob: any, callback: any) {
      if (!blob.size) return ElMessage.warning('暂无资源!')
      if (blob.type !== 'application/json') return callback(blob)
      const fr: any = new FileReader()
      fr.onloadend = function () {
        try {
          callback(JSON.parse(fr.result))
        } catch (err) {
          ElMessage.warning('资源数据有误!')
        }
      }
      fr.readAsText(blob)
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    blobType.ts 文件中(用来匹配文件的下载格式)

    export const blobType: Record<string, string> = {
      aac: 'image/audio/aac',
      abw: 'application/x-abiword',
      arc: 'application/x-freearc',
      avi: 'video/x-msvideo',
      azw: 'application/vnd.amazon.ebook',
      bin: 'application/octet-stream',
      bmp: 'image/bmp',
      bz: 'application/x-bzip',
      bz2: 'application/x-bzip2',
      csh: 'application/x-csh',
      css: 'text/css',
      csv: 'text/csv',
      doc: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
      eot: 'application/vnd.ms-fontobject',
      epub: 'application/epub+zip',
      exe: 'application/x-msdownload',
      gif: 'image/gif',
      htm: 'text/html',
      html: 'text/html',
      ico: 'image/vnd.microsoft.icon',
      ics: 'text/calendar',
      jar: 'application/java-archive',
      jpeg: 'image/jpeg',
      jpg: 'image/jpeg',
      js: 'text/javascript',
      json: 'application/json',
      jsonld: 'application/ld+json',
      mid: 'audio/midi audio/x-midi',
      midi: 'audio/midi audio/x-midi',
      mjs: 'text/javascript',
      mp3: 'audio/mpeg',
      mpeg: 'video/mpeg',
      mpkg: 'application/vnd.apple.installer+xml',
      odp: 'application/vnd.oasis.opendocument.presentation',
      ods: 'application/vnd.oasis.opendocument.spreadsheet',
      odt: 'application/vnd.oasis.opendocument.text',
      oga: 'audio/ogg',
      ogv: 'video/ogg',
      ogx: 'application/ogg',
      otf: 'font/otf',
      png: 'image/png',
      pdf: 'application/pdf',
      ppt: 'application/vnd.ms-powerpoint',
      pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
      rar: 'application/x-rar-compressed',
      rtf: 'application/rtf',
      sh: 'ima',
      svg: 'image/svg+xml',
      swf: 'application/x-shockwave-flash',
      tar: 'application/x-tar',
      tif: 'image/tiff',
      tiff: 'image/tiff',
      ttf: 'font/ttf',
      txt: 'text/plain',
      vsd: 'application/vnd.visio',
      wav: 'audio/wav',
      weba: 'audio/webm',
      webm: 'video/webm',
      webp: 'image/webp',
      woff: 'font/woff',
      woff2: 'font/woff2',
      xhtml: 'application/xhtml+xml',
      xls: 'application/vnd.ms-excel',
      xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
      xml: 'text/xml',
      xul: 'application/vnd.mozilla.xul+xml',
      zip: 'application/zip',
      '3gp': 'video/3gpp',
      '3g2': 'video/3gpp2',
      '7z': 'application/x-7z-compressed'
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73

    五、项目中实际使用

    经过上面的封装,在项目中使用二进制流下载就非常的简单了,具体示例代码如下:

    import { postFileDownloadUrl } from '@/api/fileApi'
    import { download } from '@/utils/file'
    
    const downloadFileClick = () => {
    	const parmas = {
    		// 根据接口设置请求参数
    	}
    	postFileDownloadUrl(params).then(res => {
    		// 按照download(二进制数据, 文件格式, 文件名称)使用
    		download(res, pdf, 'test')
    	})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    六、优化下载

    为了获得更好的下载体验,我们可以进一步优化:

    • a标签 添加 download 属性,会将文件名设置为该属性值
    • 使用 click 触发下载,无需用户手动点击
    • Blob数据 加工,比如设置类型、压缩等
    • 下载完成后主动释放 Object URL,避免内存泄露
      通过以上优化,我们就可以通过 Blob对象 方便实现各种文件下载需求。
  • 相关阅读:
    语义分割算法
    Python正则表达式
    kali更新源数字签名错误解决办法
    WPF中样式静态、动态资源、资源字典
    《低代码指南》——如何通过维格表实现生产采购管理
    55、MINE: Towards Continuous Depth MPI with NeRF for Novel View Synthesis
    【科研论文配图绘制】task7密度图绘制
    keil下载及安装(社区版本)
    计算机系统的层次结构
    64个热门图像分类数据集免费、高速资源分享,涵盖通用视觉、食物、艺术、医疗等多种场景
  • 原文地址:https://blog.csdn.net/SmallTeddy/article/details/134265816