Front-end file download implementation solution, Blob object enables you to download any file

Article directory

  • Preface
  • 1. What is Blob?
  • 2. Generate Blob object
  • 3. Request processing
    • 1. Request encapsulation
    • 2. According to the backend interface configuration
  • 4. Tool functions
  • 5. Actual use in projects
  • 6. Optimize downloads

Foreword

This article mainly introduces how to use Blob object to implement the file download function on the front end.

The article first introduces what a Blob object is, which represents a large binary object that can be used to represent files or binary data. Then it explains in detail several ways to generate Blob objects, and how to generate an object URL through the createObjectURL method and set it to the a tag ‘s href attribute implements file downloading. At the end of the article, some methods for optimizing the download experience are also mentioned, such as setting the download attribute and using the click method to trigger downloads.

Mastering the use of Blob can realize powerful front-end file downloading, uploading, and binary data processing functions, which is a very important ability. The content of this article is easy to understand and can help readers quickly understand the usage of Blob.

1. What is Blob?

Blob(Binary Large Object) represents a large object of binary type, which can be used to represent files or binary data. In the front end, we can generate a file object through Blob object, and then create a a tag to download the file.

2. Generate Blob object

A Blob object can be generated in the following ways:

//Generate Blob object from string
const blob = new Blob(['hello world'])

//Generate Blob object from array
const blob = new Blob([new Uint8Array([1,2,3])])

// Generate from another blob
const newBlob = blob.slice()

// Generate from canvas
canvas.toBlob(callback)

The resulting Blob object represents an immutable, raw data file-like object. Its data can be read in text or binary format, or converted into ReadableStream for data processing.

3. Request processing

1. Request encapsulation

In the file fileRequest.ts

import axios from 'axios'

//Create axios instance
const fileRequest = axios.create({<!-- -->
  timeout: 30 * 1000, // Request timeout
  responseType: 'blob', // *Key points*
  withCredentials: true
})

// request interceptor
fileRequest.interceptors.request.use(
// Omit some
)

// response interceptor
fileRequest.interceptors.response.use(
// Omit some
)

export default fileRequest

2. According to the backend interface configuration

In the file fileApi.ts

import fileRequest from './utils/fileRequest'

//File download interface
export function postFileDownloadUrl(data = {<!-- -->}) {<!-- -->
return fileRequest({<!-- -->
url: 'backend url',
method: 'POST',
data
})
}

4. Utility functions

We encapsulate a download tool function to process the download of any binary file returned by the backend

In the file.ts file

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('This format is not supported yet!')
  const blob = new Blob([file], {<!-- --> type })
  const downloadElement = document.createElement('a')
  const href = window.URL.createObjectURL(blob) // Create download link
  downloadElement.href = href
  downloadElement.download = fileName // file name after downloading
  document.body.appendChild(downloadElement)
  downloadElement.click() // Click to download
  document.body.removeChild(downloadElement) // Remove element after download is complete
  window.URL.revokeObjectURL(href) // Release the blob object
}

export function formatFileType(fileFormat: string) {<!-- -->
  return blobType[fileFormat]
}

export function blobToFileReader(blob: any, callback: any) {<!-- -->
  if (!blob.size) return ElMessage.warning('No resources yet!')
  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('The resource data is incorrect!')
    }
  }
  fr.readAsText(blob)
}

In the blobType.ts file (used to match the download format of the file)

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'
}

5. Actual use in projects

After the above encapsulation, it is very simple to use binary stream download in the project. The specific sample code is as follows:

import {<!-- --> postFileDownloadUrl } from '@/api/fileApi'
import {<!-- --> download } from '@/utils/file'

const downloadFileClick = () => {<!-- -->
const parmas = {<!-- -->
//Set request parameters according to the interface
}
postFileDownloadUrl(params).then(res => {<!-- -->
//Use according to download (binary data, file format, file name)
download(res, pdf, 'test')
})
}

6. Optimize downloads

In order to get a better download experience, we can further optimize:

  • Adding the download attribute to the a tag will set the file name to the attribute value
  • Use click to trigger downloads without requiring the user to manually click
  • Process Blob data, such as setting type, compression, etc.
  • After the download is completed, Object URL is actively released to avoid memory leaks.
    Through the above optimization, we can easily implement various file download needs through Blob object.