The method of front-end realization of file download

Front-end implementation of file download

Front-end downloads are generally divided into two situations. One is that the back-end directly gives a file address, which can be downloaded by opening it through a browser. The other requires sending a request. The back-end returns binary stream data, and the front-end parses the stream data to generate a URL. , to achieve downloading.

1. location.href

For some file formats that cannot be recognized by the browser, you can directly enter the url in the address bar of the browser to trigger the download function of the browser. There is no problem with downloading a single file, but if you download multiple files, clicking too quickly will reset the previous request

Applicable scene:

  • get request
  • single file download
window.location.href = url;

Two, window.open

Similar to location.href

window.open(url);

Three, a label

Direct downloads only work with files that your browser doesn't recognize. If it is a file format supported by the browser, such as html, jpg, png, pdf, etc., the file download will not be triggered, but will be directly parsed and displayed by the browser. In this case, you can use the a tag to download the file, the download attribute The file name can be set. It is suitable for downloading a single file. If you download multiple files, clicking too fast will reset the previous request.

Applicable scene:

  • get request
  • single file download
  • need custom filename
//写法1
const download = (filename, url) => {
    
    
    let a = document.createElement('a'); 
    a.style = 'display: none'; // 创建一个隐藏的a标签
    a.download = filename;
    a.href = url;
    document.body.appendChild(a);
    a.click(); // 触发a标签的click事件
    document.body.removeChild(a);
}
// 写法2
<a href="/images/download.jpg" download="myFileName">

Note: Sometimes we still need to download directly for the file format recognized by the browser. You can declare the Content-Disposition information of the header of the file, tell the browser that the link is a download attachment link, and you can declare the file name

Content-Disposition: attachment; filename="filename.xls"

4. File flow

If you need to use a post request, and the backend returns a file stream, then the front end needs to convert the file stream into a link, and then download it. The binary stream looks like this: image.pngApplicable scenarios:

  • post request
  • get request
  • multiple files

1. Method of request

Note: JQuery cannot be used because JQuery does not support the blob type.

Native js writing method

const req = new XMLHttpRequest();
req.open('POST', '/download/excel', true);
req.responseType = 'blob'; //如果不指定,下载后文件会打不开
req.setRequestHeader('Content-Type', 'application/json');
req.onload = function() {
    
    
    var content = req.getResponseHeader("Content-Disposition") ;
    // 文件名最好用后端返的Content-disposition
    // 需要后端设置 Access-Control-Expose-Headers: Content-disposition 使得浏览器将该字段暴露给前端
    var name = content && content.split(';')[1].split('filename=')[1];
    var fileName = decodeURIComponent(name)
    downloadFile(req.response,fileName)
};
req.send( JSON.stringify(params));

axios wording

download(url: string, body: any, fileName: string, method?) {
    
    
	return axios({
    
    
	  method: method ||'post',
	  headers: {
    
    
	    'Content-Type': 'application/json; charset=utf-8'
	  },
	  url,
	  responseType: 'blob',
	  headers: {
    
     //如果需要权限下载的话,加在这里
	        Authorization: '123456'
	    }
	  data: JSON.stringify(params),
	  timeout: 60 * 1000
	}).then((res: any) => {
    
    
	   if (!res) {
    
    
	     message.error('下载失败')
	     return
	   }
	   console.log('res:', res)
	   let url = window.URL.createObjectURL(new Blob([res], {
    
     type: 'application/vnd.ms-excel' }))
	   let link = document.createElement('a')
	   link.style.display = 'none'
	   link.href = url
	   if (!fileName || typeof fileName != "string") {
    
    
	     fileName = "下载文件"
	   }
	   link.setAttribute('download', fileName + '.xlsx')
	   document.body.appendChild(link)
	   link.click()
	   document.body.removeChild(link); //下载完成移除元素
	   window.URL.revokeObjectURL(url); //释放掉blob对象
	 })
}

2. How to download files

Download via URL.createObjectURL()

URL.createObjectURL()The static method creates a DOMString containing a URL representing the object given in the parameter. The life cycle of this URL is bound to the document in the window that created it.

downloadFile:function(data,fileName){
    
    
    // data为blob格式
    var blob = new Blob([data]);
    var downloadElement = document.createElement('a');
    var 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);
}

Download via #FileReader.readAsDataURL()

readAsDataURL()method reads the specified Blob or File object. The read operation is an asynchronous operation. When the read is completed, you can get a data:URL format string (base64 encoded) from the onload callback function through the result attribute of the instance object. This string is the content of the read file, which can be Put it in the href attribute of the a tag.

downloadFile:function(data,fileName){
    
    
   const reader = new FileReader()
   // 传入被读取的blob对象
   reader.readAsDataURL(data)
   // 读取完成的回调事件
   reader.onload = (e) => {
    
    
       let a = document.createElement('a')
       a.download = fileName
       a.style.display = 'none'
       // 生成的base64编码
       let url = reader.result
       a.href = url
       document.body.appendChild(a)
       a.click()
       document.body.removeChild(a)
   }
}

the difference between the two

  • return value

FileReader.readAsDataURL(blob) can get a base64 string
URL.createObjectURL(blob) gets a memory url of the current file

  • Memory

FileReader.readAsDataURL(blob) automatically clears the URL from the memory according to the js garbage collection mechanism. createObjectURL(blob) exists in the current document, and the clearing method is manually cleared by revokeObjectURL()

  • Implementation modalities

FileReader.readAsDataURL(blob) is returned by callback, asynchronously executed
URL.createObjectURL(blob) is returned directly, synchronously executed

  • multiple files

When FileReader.readAsDataURL(blob) processes multiple files at the same time, one file needs to correspond to one FileReader object
URL.createObjectURL(blob) returns in sequence, no effect

  • Comparison of advantages

URL.createObjectURL(blob) obtains the address of the local memory container URL, which is convenient for previewing. It is necessary to pay attention to the problem of manually releasing the memory, and the performance is excellent.
FileReader.readAsDataURL(blob) can be directly converted to base64format and used directly for business

Five, plug-indownloadjs

download

 npm install --save downloadjs

import plugin

import download from "downloadjs"
// or
const download = require('downloadjs')

use

  export const downloadFile = (res, type, filename) => {
    
    
    // 将二进制流转成blob对象
    const blob = new Blob([res], {
    
    
      type: type
    })
    // 调用插件方法
    download(blob, filename, type);
  }

Guess you like

Origin blog.csdn.net/MoXinXueWEB/article/details/126092614