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
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)