Make writing a habit together! This is my first day to participate in the “Gold Digging Day New Plan · April More text challenge”, click to see the details of the activity.

More elegant file download method: front-end asynchronous file download scheme

Demand analysis:

Downloading files is usually done by opening a non-asynchronous GET request, but this way we have no way of knowing the browser’s progress or when the download is complete (note the difference between the browser and the application). For example, we need to add custom loading during the download process and do other things after the download is complete. This can be achieved by asynchronously retrieving the file stream and then downloading the file.

Main ideas:

The first step is to get the character stream or BLOB returned by the interface via an asynchronous request (axios or XHR, etc.). If the character stream is returned, the front end can convert it to a BLOB by new blob ().

Step 2, download the BLOB with the A tag.

The third part, when the download is complete, releases the BLOB and removes the A tag from the document.

Note: to solve the ie does not support direct download blob resources, through the window. The navigator. MsSaveOrOpenBlob (blob, filename)

Scenario 1: Use AXIos to asynchronously fetch the BLOB

// Note that when downloading Excel, axios or XHR requests require xhr.responseType = "blob"
// Otherwise, the downloaded Excel will not open
// Return type blob
downloadExcel (params) {
  // Wrapped axios
  this.$api.downloadExcel(params).then(res= > {
    let filename = res.headers['filename']
    // const blob = new blob ([res.data]) // Converts character stream to blob object
    blobDownload(res.data, decodeURIComponent(filename))
  }).finally(() = > {
    this.loading = false})},/** * Download file: Download the blob object file *@param blob
 * @param filename* /
export function blobDownload (blob, filename = 'file. TXT') {
  let url = window.URL.createObjectURL(blob)
  Internet Explorer does not support direct download of BLOB resources
  if ('msSaveOrOpenBlob' in navigator) {
    window.navigator.msSaveOrOpenBlob(blob, filename)
    return
  }
  let link = document.createElement('a')
  link.style.display = 'none'
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link) // Remove the element after downloading
  window.URL.revokeObjectURL(url) // Release the blob object
}

// Create an axios instance
const service = axios.create({
  headers: {
    'kms-token': localStorage.getItem('token') | |' '
  },
  baseURL: config.ip,
  timeout: 2 * 600000.withCredentials: true // Indicates whether credentials are required for cross-domain requests. After enabling this function, the backend server must enable this function
})

// Request interceptor
service.interceptors.request.use(
  config= > {
    const token = localStorage.getItem('token')
    if (config.url === '/api/excel/upload/knowledge/download') {
       // Return type blob. Excel cannot be opened without setting blob
      config.responseType = 'blob'
      // config.headers['Content-Type'] = 'application/x-download'
    }
    return config
  },
  error= > {
    // console.warn(error)
    return Promise.reject(error)
  }
)
Copy the code

Method 2: Get bloBS asynchronously using XHR

downloadExcel2 (params) {
  const token = localStorage.getItem('token') | |' '
  const url = 'http://192.168.0.0' + ': 8079 /' + '/api/excel/download'
  let xhr = new XMLHttpRequest()
  / / POST way
  xhr.open('POST', url + '? timeStamp=' + new Date().getTime(), true)
  xhr.setRequestHeader('Cache-Control'.'no-cache')
  xhr.setRequestHeader('Content-type'.'application/json')
  xhr.setRequestHeader('token', token)
  // Return type blob. Excel cannot be opened without setting blob
  xhr.responseType = 'blob'
  // Define the request completion handler, before the request can also add load box/disable download button logic
  xhr.onload = function () {
    // Request completed
    if (this.status === 200) {
      let blob = this.response
      let reader = new FileReader()
      // Convert to base64, which can be directly placed in the a expression href
      reader.readAsDataURL(blob)
      reader.onload = function (e) {
        // When the conversion is complete, create an A tag for downloading
        let a = document.createElement('a')
        a.download = 'Statement of receipts and expenditures. XLSX'
        a.href = e.target.result
        a.click()
      }
    }
  }
  xhr.send(JSON.stringify(params))
}
Copy the code

General synchronous file download scheme

download (url) {
  const a = document.createElement('a')
  a.href = url // Download the link
  a.download = 'filename' // Set the Download property to tell the browser to perform the download operation, which can be assigned a filename
  a.click()
}
Copy the code