Requirements
Through the A link method, the files obtained from the background are downloaded to the local computer, so that they can be downloaded on both mobile and PC terminals.
Question
After requesting the file stream generated by the backend through ajax, a BLOB file is created for downloading. On the PC side and the mobile Android side, it can be downloaded to the local and corresponding mobile phones. On the IOS side, the corresponding blob file address is directly previewed. Instead of downloading the corresponding file stream, the solution can also be downloaded on IOS (Safari browser only)
Steps
1. Through request, the value of responseType is ‘arraybuffer’, request the corresponding file stream
uni.request({ ...handleRes, responseType: 'arraybuffer', success(res) { // console.log(res, 'return data'); // This is the returned file stream const file = res.data; \t\t\t\t\t }, fail() { uni.hideLoading(); \t\t\t\t\t } })
2. By converting files into blob objects
let blob = null; if (headerDis.indexOf(tyepList.toString()) != -1) { blob = new Blob([file], { type: 'application/octet-stream;charset=UTF-8', }) } else { blob = new Blob([file], { type: headerInfo['content-type'] || 'application/octet-stream;charset=UTF-8', }) }
3. Create a link and download through the download attribute
async linkTodownloadFile(blob, fName) { if (window.navigator.msSaveOrOpenBlob) { window.navigator.msSaveBlob(blob, fName); return false; } const url = window.URL.createObjectURL(blob) const link = document.createElement('a') link.style.display = 'none' link.href = url; link.setAttribute('download', fName) document.body.appendChild(link) if (document.all) { link.click(); } else { // Compatible with Firfox const evt = document.createEvent('MouseEvents'); evt.initEvent('click', true, true); link.dispatchEvent(evt); } document.body.removeChild(link) // Remove element after download is complete window.URL.revokeObjectURL(url); uni.hideLoading(); common.toast(107) }
Note: The main thing here is that if you customize the type of blob on the IOS side, the download attribute will only add the file name without a suffix, which will form a double suffix. And if the type is steam, it will be preview and set to steam If so, the file will be downloaded directly, which is the reason for the judgment in the second step
4. Complete code
uni.request({ url: 'xxx', responseType: 'arraybuffer', success(res) { // console.log(res, 'return data'); const file = res.data; const headerInfo = res.header; /** Get file name */ let fName = ''; /** Determine whether it is a customizable type or default */ const tyepList = ['pdf']; const headerDis = headerInfo['content-disposition']; if (headerDis) { const requestFileInfo = headerDis.split(';')[1]; if (store.state.app.SYSTEM_INFO.platform == 'ios') { if (headerDis.indexOf(tyepList.toString()) != -1) { fName = requestFileInfo; } else { fName = requestFileInfo.split('.')[0]; } } else { fName = requestFileInfo; } } else { /** Determine whether the file has a type, if not, use the effect header */ const fType = file.type || headerInfo['content-type'].split(';')[0]; for (const key in fileTypeConfig) { if (fileTypeConfig[key].indexOf(fType) != -1) { if (store.state.app.SYSTEM_INFO.platform == 'ios') { fName = `${fileName}`; } else { fName = `${fileName}.${key}`; } break } } } \t\t\t\t\t/** start download */ let blob = null; if (headerDis.indexOf(tyepList.toString()) != -1) { blob = new Blob([file], { type: 'application/octet-stream;charset=UTF-8', }) } else { blob = new Blob([file], { type: headerInfo['content-type'] || 'application/octet-stream;charset=UTF-8', }) } /** Determine whether to perform logical processing for JSON */ if (fName.indexOf('json') != -1) { //Read data through FileReader const reader = new FileReader(); // reader.readAsBinaryString(blob); reader.readAsText(blob, 'utf8'); reader.onload = function() { var content = JSON.parse(this.result); //This is the parsed data if (content.code == 200) { // common.toast(fName); that.linkTodownloadFile(blob, fName); resolve(); } else { isLoading & amp; & amp; uni.hideLoading(); common.toast(content.msg || 400); } } } else { // common.toast(fName); that.linkTodownloadFile(blob, fName); resolve(); } }, fail() { uni.hideLoading(); common.toast(108) reject(); } })
5. Contents of attachment fileTypeConfig
export default { xls: 'application/vnd.ms-excel', xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', csv: 'text/csv', doc: 'application/msword', docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', pdf: 'application/pdf', ppt: 'application/vnd.ms-powerpoint', pptx: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', png: 'image/png', gif: 'image/gif', jpeg: 'image/jpeg', jpg: 'image/jpeg', mp3: 'audio/mpeg', aac: 'audio/aac', html: 'text/html', css: 'text/css', js: 'text/javascript', json: 'application/json', abw: 'application/x-abiword', arc: 'application/x-freearc', avi: 'video/x-msvideo', azw: 'application/vnd.amazon.ebook', bin: 'application/octet-stream', bmp: 'image/bmp', bz: 'application/x-bzip', bz2: 'application/x-bzip2', csh: 'application/x-csh', eot: 'application/vnd.ms-fontobject', epub: 'application/epub + zip', htm: 'text/html', ico: 'image/vnd.microsoft.icon', ics: 'text/calendar', jar: 'application/java-archive', jsonld: 'application/ld + json', mid: 'audio/midi audio/x-midi', midi: 'audio/midi audio/x-midi', mjs: 'text/javascript', mpeg: 'video/mpeg', mpkg: 'application/vnd.apple.installer + xml', odp: 'application/vnd.oasis.opendocument.presentation', ods: 'application/vnd.oasis.opendocument.spreadsheet', odt: 'application/vnd.oasis.opendocument.text', oga: 'audio/ogg', ogv: 'video/ogg', ogx: 'application/ogg', otf: 'font/otf', rar: 'application/x-rar-compressed', rtf: 'application/rtf', sh: 'application/x-sh', svg: 'image/svg + xml', swf: 'application/x-shockwave-flash', tar: 'application/x-tar', tif: 'image/tiff', tiff: 'image/tiff', ttf: 'font/ttf', txt: 'text/plain', vsd: 'application/vnd.visio', wav: 'audio/wav', weba: 'audio/webm', webm: 'video/webm', webp: 'image/webp', woff: 'font/woff', woff2: 'font/woff2', xhtml: 'application/xhtml + xml', xml: 'text/xml', xul: 'application/vnd.mozilla.xul + xml', zip: 'application/zip,application/x-zip-compressed', }