在B端项目中,经常遇到报表类的需求。即一个表单,然后查询出多种数据,最后导出为excel文件。
这里就需要遇到文件下载类的开发。通常,有以下几种方式:

打开一个文件地址

前端传递表单参数,后端生成文件,然后返回静态文件地址,然后前端可以在空白页面打开这个地址,文件就会被下载。

下载文件流

前端传递表单参数,后端生成文件,然后返回文件流,最后前端将文件流保存。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
// 前后端采用不同的编码格式会使文件名乱码,暂未解决,work around:可以前端直接定义文件名而不从content-disposition获取
import axios from 'axios';
axios.request({
method: 'get',
url: url,
params: params,
responseType: 'blob'
}).then(res => {
let filename = res.headers['content-disposition'];
let filetype = res.headers['content-type'];
const blob = new Blob([res.data], {type: filetype});
// IE hack; see http://msdn.microsoft.com/en-us/library/ie/hh779016.aspx
const result = filename.split(';filename=')[1];
if (result && result.endsWith('.csv')) {
filename = result;
} else {
filename = `${result || filename}.csv`;
}
if (window.navigator.msSaveOrOpenBlob) {
window.navigator.msSaveBlob(blob, filename);
} else {
const a = window.document.createElement('a');
a.href = window.URL.createObjectURL(blob, {type: 'text/plain'});
a.download = filename;
document.body.appendChild(a);
// IE: "Access is denied"; see: https://connect.microsoft.com/IE/feedback/details/797361/ie-10-treats-blob-url-as-cross-origin-and-denies-access
a.click();
document.body.removeChild(a);
}
}).catch(err => {
// error handle
});

传递数据,由前端生成文件

前端post传递表单参数,后端返回数据(data),前端根据返回的数据生成excel文件。
这里需要用到 js-xlsx
js-xlsx 是一个方便操作xlsx文件的js工具库, node环境及客户端环境都可以用。

1
2
3
4
5
6
7
8
9
10
11
import XLSX from 'xlsx';
import axios from 'axios';
axios.post(url, params).then(res => {
let result = res.data.list; // result should be array of arrays
const ws = XLSX.utils.aoa_to_sheet(result);
const wb = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(wb, ws, "tabname");
XLSX.writeFile(wb, 'filename.xlsx');
}).catch(err => {
// error handle
})