The default and simplest download method is: window.open (backend interface API path) , but this method has disadvantages: because it is a new window opening method, the front-end display will flash every time.
In addition, if you use the window.open (file URL) method:
- PDF, office documents, psd: direct download.
- Pictures and txt: When previewing in a new window, it will not be downloaded; and when txt is previewed, Chinese garbled characters sometimes appear.
1. Download according to file URL
Implementation principle: Download through a tag.
/**
* @method 下载单个文件(文件类型可任意:.png、txt、office文档、.psd等)
* @param { String } url - 文件的http完整路径, 如:http: //xxx.png
* @param { String } fileName - 文件名,注意是要带文件后缀名,如:xxx.png
* @doc https://blog.csdn.net/weixin_39547158/article/details/110851570
*/
export function downloadFile(url: string, fileName: string) {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.responseType = 'blob';
xhr.upload.onprogress = (e) => {
if (e.lengthComputable) {
let progress = e.loaded / e.total;
console.log('文件上传进度是', progress);
}
};
xhr.onload = function () {
const url = window.URL.createObjectURL(xhr.response);
const eleLink = document.createElement('a');
eleLink.href = url;
eleLink.download = `${fileName}`;
eleLink.style.display = 'none';
document.body.appendChild(eleLink);
eleLink.click();
document.body.removeChild(eleLink);
resolve('success');
};
xhr.onerror = (e) => {
console.log('请求错误回调', e);
message.warning('下载文件失败')
reject(e);
};
xhr.send();
});
}
2. Excel file: call the background interface to return the file stream, and the front-end downloads the file
Implementation principle: Call the backend interface and return blob, and the front end uses the file-saver library to implement downloading.
// 下载excel文件
import { saveAs } from 'file-saver';
const downloadTemplate = async () => {
try {
const params = { ... } // 传参
const res = await generateDownStreamReconciliationUsingGET(params);
// res为返回结果
if (res) {
const blob = new Blob([res], { type: 'application/vnd.ms-excel' });
FileSaver.saveAs(blob, '对账单.xlsx');
console.log('对账单下载成功')
}
} catch (e) {
console.log(e);
} finally {
console.log('finally')
}
};
// 生成对账excel模板表格API
export async function generateDownStreamReconciliationUsingGET(
params: API.generateDownStreamReconciliationUsingGETParams,
options?: { [key: string]: any },
) {
return request<any>(
`${process.env.APP_HOST_WAYBILL}/xxx/generateDownStreamReconciliation`,
{
method: 'GET',
responseType: 'blob', // 必须写该行,否则:后台返回的是string,不是blob且文件下载后,会出现打不开问题。
params: {
...params,
},
...(options || {}),
},
);
}
3. Multi-file URL download, front-end generated compressed package download
Implementation principle: jszip library + file-saver library
import { getBlobOfUrl } from '@/services/common';
import { saveAs } from 'file-saver';
import JSZip from 'jszip';
import { message } from 'antd';
/**
* @method 同时下载多文件,并生成一个压缩包
* @param { Object[] } fileInfoList - 文件列表
* @param { String } urlField - 文件URL的字段名
* @param { String } fileNameField - 文件名的字段名
* @param { String } folderName - 压缩包 & 文件夹名称
*/
export function downloadAsZip(
fileInfoList: any[],
folderName = '文件压缩包',
urlField = 'filePath',
fileNameField = 'name',
) {
return new Promise((resolve, reject) => {
const zip = new JSZip();
// const folder = zip.folder(folderName); // 创建文件夹
const promisesList = fileInfoList.map((item) => {
return getBlobOfUrl(item[urlField])
.then((data) => {
// console.log(data); // Blob
// folder.file(item[fileNameField], data, { binary: true }); // 往文件夹中存放文件
zip.file(item[fileNameField], data, { binary: true }); // 不创建文件夹
})
.catch((e) => {
console.log(e);
message.warning(e?.message || '获取文件流失败')
});
});
Promise.all(promisesList)
.then(() => {
zip
.generateAsync({ type: 'blob' })
.then((content) => {
saveAs(content, folderName);
resolve('success');
})
.catch((e) => {
message.warning(e?.message || '生成压缩包失败')
reject(e);
});
})
.catch((e) => {
message.warning(e?.message || '批量获取文件流失败')
reject(e);
});
});
}
import { request } from 'umi';
/**
* @method 根据文件URL获取blob数据流的API
* @param { String } fileUrl - 文件完整路径,如:http://xxx.png
*/
export function getBlobOfUrl(fileUrl: string) {
return request(fileUrl, {
method: 'GET',
responseType: 'blob', // 设置后台返回的内容类型为blob
params: {
notAuthorization: true,
},
});
}