Requirements and Problems

  • It is common to find sites that download documents through buttons, and the browser downloads silently (without refreshing), and you can see the status of the download, etc.
  • The logic in daily development is that the back end returns the file stream with the header, and the front end directly accesses the address with the A tag to implement the download. The download name is defined in the back end header. In this way, the front end does not need any operation, just follow the normal page access link.
  • Until one day, I sent data to the background through AXIos post, and the background returned the file to me after processing, but I only got garbled characters and could not download the file, so I kept wondering if there was a way to make Axios download the file.

To sum up: the traditional way to download a file is to be completely back-end, with the front end simply accessing the address (get) to download it. Note that the access here is get, as the A tag, window.open, and location.href are all get. Disadvantages of this approach:

  1. The HTTP GET mode carries few parameters
  2. Unable to download silently (browser always refreshes)
  3. There are some front-end interaction details that cannot be implemented because the browser is being refreshed
  4. The back-end storage is generally not Chinese names, and the return of downloaded files will rarely be customized, ugly file names.

The solution

Later, after exploration, it was found that front-end download can be realized in the form of file stream data obtained by XHR request, processed by BLOB objects, and then accessed by A tag. The latest HTML5 provides a download attribute for a tag, which can force the download of files and provide attribute values as file names. This allows you to download files using AXIos requests, blob objects, and a tag with a Download attribute. You can post a lot of data (I want to pass AN HTML string) to the background and back without having to watch the browser go around. You can also front-end define file names.

code

     download(config,filename){
      config['responseType'] = 'arraybuffer';// Key point 1
       
      // config['blobType'] = 'application/vnd.ms-excel';
      const blobType = 'application/force-download';// Critical point 2
      const theConfig = this._configSerialize(config);// Ignore the method I encapsulated to serialize config before returning it to Axios
      return axios(theConfig).then((res) = > {
        
        const blobo = new Blob([res.data],{type:blobType})
        
        const archor = document.createElement('a');
        const href = window.URL.createObjectURL(blobo)// Keypoint 3
        archor.setAttribute('href',href)
        // * Key points: To use the Download attribute, you must use the HTML5 page, and it does not refresh. The file name and extension are controlled here */
        archor.setAttribute('download',filename)// Keypoint 4
        archor.click();
         return true; })}//use
    //download(axiosConfig,'abc.json')
Copy the code
  • Key point 1: This must be specified when passing the request configuration to AXIosresponseTypeThe author has tried bloB and ArrayBuffer, both of which are feasible
  • Key point 2: When a new blob object is passed the configuration, type needs to be specified as the MIME type of the file, which I tried to findapplication/force-downloadProbably generic, and you don’t even need to set headers on the back end (I tried to send JPG, PDF, XLS)
  • Key point 3: UseURL.createObjectURLCreate a bloB instance as a link (translated as a BLOb object into an accessible href link address for a tag)
  • Key point 4: The last point is to set the Download attribute for the created A tag. Note that the file name should have an extension, otherwise the downloaded file will not be recognized. Just take the trouble.

Using this function is as simple as passing in the configuration of the AXIos request and a file name. I tried to download whatever the back end returned (a plain text string is fine). The type of file to download is specified by the extension of the Download attribute. Therefore, you should know exactly what format of file is returned from the back end when using it. Otherwise, the file will not be opened (you can download and change it back again, and users will not understand).

This is a great way to download files, and the back end just returns strings or streams. There is no need for complicated front-end setup, just the right extension can be downloaded. It also solves the problem of get access parameter limitation.

Note: The Download attribute must require the HTML page type to be HTML5: <! The Doctype HTML > download attribute can also force files to be downloaded. If the header is not set in the background when you access image resources or PDF documents using the A tag, the file will be displayed in the browser instead of being downloaded.

disadvantages

Downloading files in this way has an obvious drawback, as it is not recognized and handled when a background error returns a Boolean or JSON object. Because we set responseType, Axios takes the requested resource and wraps it as an ArrayBuffer object. Res.data is always an ArrayBuffer object. Some of the workarounds on the web are to set some error-recognition code in the header through a pre-and-post-convention, so axios can take the header and judge it before deciding whether to download the file.