So light, so heavy: image download and compressed package download

0. Origin

Download. Different text streams have different download methods.

1. Picture download

I directly, uh, use the previous method of downloading pictures, change the acquisition and download name of the text stream, and dare to use it directly. As a result, er, the direct file is damaged and cannot be opened.

    //Export picture
    exportPic() {
      //The toDataURL() method of canvas returns a data URL containing the image display
      const dataURL = this.canvas.toDataURL({
        width: this.canvas.width,
        height: this.canvas.height,
        left: 0,
        top: 0,
        format: "png",
      });
      //Create an a tag that points to the URL address of the picture,
      //Click to download canvas Png picture
      const link = document.createElement("a");
      link.download = "canvas.png";
      link.href = dataURL;
      //Mount an element on the Body object of the current document. Here is the a tag
      //Simulate the click of a tag and remove the element after downloading
      document.body.appendChild(link);
      link.click();
      document.body.removeChild(link);
    },

2. Correct operation of compressed package download

2.1 Axios

axios used, from its packaging method. Has the response been changed

const instance = axios.create({
  baseURL,
  timeout: requestTimeout,
  headers: {
    "Content-Type": contentType,
  }
});

instance.interceptors.response.use(
  (response) => {
    if (loadingInstance) loadingInstance.close();

    const { data, config } = response;
    console.log('response: ', response);
    const { code, message } = data;

    let successFlag = response.status;
    // Normal operation Code array
    const codeVerificationArray = isArray(successCode)
      ? [...successCode]
      : [...[successCode]];
    // Is the operation normal? Old Version
    // if (codeVerificationArray.includes(code)) {
      // New Version ***
    if (successFlag === 200) {
        // Special Blob Type
      if (response.config.responseType === 'blob') {
        return response
      } else {
        return data;
      }
    } else {
      console.log(code, message)
      handleCode(code, message);
      return Promise.reject(
        "Request exception interception:" +
        JSON.stringify({ url: config.url, code, message }) || "Error"
      );
    }
  },
  (error) => {
    if (loadingInstance) loadingInstance.close();
    const { response, message } = error;
    if (error.response && error.response.data) {
      const { status, data } = response;
      handleCode(status, data.message || message);
      return Promise.reject(error);
    } else {
      let { message } = error;
      if (message === "Network Error") {
        message = "Back end interface connection exception";
      }
      if (message.includes("timeout")) {
        message = "Backend interface request timeout";
      }
      if (message.includes("Request failed with status code")) {
        const code = message.substr(message.length - 3);
        message = "Back end interface" + code + "abnormal";
      }
      Vue.prototype.$baseMessage(message || `Back end interface unknown exception`, "error");
      return Promise.reject(error);
    }
  }
);

2.2 Response

Note that when successful, the data in the response is returned directly before, and we are getting the file stream. Note that the responseType must be blob

  // `responseType ` indicates the data type of the server response. It can be 'arraybuffer', 'blob', 'document', 'json', 'text', 'stream'
  responseType: 'json', // default

Instructions · Axios Chinese instructions · look at the cloud (kancloud.cn)

For example, here is my method of downloading compressed packages

// Download MagicBoxVersion 
export function downloadMagicBoxEdition(id) {
  return request({
    url: `/.../export?id=${id}`,
    method: 'POST',
    baseURL: baseURLB,
    responseType: 'blob',
  })
}

2.3 Data

At this step, in the download function of the download button, pass a value to obtain the corresponding file stream. The next step is how to download:

    handleExport(row) {
      downloadMagicBoxEdition(row.id).then((res) => {
        console.log(res);
        let blob = new Blob([res.data], {
          type: "application/octet-stream;charset=utf-8",
        }); // res.data is the file stream returned by the interface
        let name = res.headers["content-disposition"];
        let fileName = `${decodeURIComponent(
          name.split(";")[1].split("=")[1]
        )}`.replace("zip", ".zip");
        if ("download" in document.createElement("a")) {
          // Non IE Download
          const elink = document.createElement("a");
          elink.download = fileName;
          elink.style.display = "none";
          elink.href = URL.createObjectURL(blob);
          document.body.appendChild(elink);
          elink.click();
          URL.revokeObjectURL(elink.href); // Release URL object
          document.body.removeChild(elink);
        } else {
          // IE10 + download
          navigator.msSaveBlob(blob, fileName);
        }
      });
    },

2.4 Title

There is a fileName and file name on it. The back end uses content disposition to pass it.

filename

Followed by a string of the initial name of the file to be transferred. This parameter is always optional and cannot be used blindly: the path information must be discarded, and some conversion must be carried out to comply with the server file system rules. This parameter is mainly used to provide display information. When used with content disposition: attachment, it is used as the default file name presented to the user in the Save As dialog box.

Content-Disposition - HTTP | MDN (mozilla.org)

        let name = res.headers["content-disposition"];        
		let fileName = `${decodeURIComponent(
          name.split(";")[1].split("=")[1]
        )}`.replace("zip", ".zip");

This section in the download function obviously takes the passed file name from the beginning.

PS: Here we must pay attention to whether the response transmitted by axios encapsulated in axios in the first step is the complete response, which is generally transmitted Data, the header part cannot be obtained!

appendix

Previously written upload method

When I look back, the man is in the dim light: upload method - Music Tour - blog Garden (cnblogs.com)

Reference articles on file upload, but it's OK to use El upload directly

It's enough to upload files and understand these 8 scenarios - Nuggets (juejin.cn)

Keywords: axios Vue

Added by nezona on Sat, 01 Jan 2022 17:42:18 +0200