场景:
在很多时候需要从前端下载文件的情况,最为典型就是导出指定格式的数据
一般存在两种方式:
- 请求接口之后,直接打开请求该文件的地址,下载到本地。
- 请求接口之后,将获取到的文件数据格式转换之后,再下载到本地。
第一种
window.location.href = res.request.responseURL
第二种
第二种方式,就是正常的api请求,获取到文件数据之后,在本地模拟一次点击按钮下载,不过这次下载不是再向后端请求一次api,而是把第一次请求api之后,后端返回的文件数据转换成合适的格式之后下载下来。
//前端JS代码
exportFile(this.queryParam).then(res => {
//res是后端返回的数据
//正常格式res.data可以正确根据自己请求内容进行更改
if (res.status === 200) {//根据自己需要进行替换
const xlsx = 'application/vnd.ms-excel'
const blob = new Blob([res.data], { type: xlsx })
const a = document.createElement('a') // 转换完成,创建一个a标签用于下载
// const name = res.headers['content-disposition']
// a.download = name.split('=')[1]
a.download = `${this.$t('menu.operatelog')}.xlsx`
a.href = window.URL.createObjectURL(blob)
a.click()
a.remove()
document.body.removeChild(a) //也可以这么移除
// 直接打开下载文件的链接
// window.location.href = res.request.responseURL
}
})
axios请求代码
export function exportFile (parameter) {
return axios({
url: `/export`,// 绝对路径请求地址 https:127.0.0.1:8080/xm/exprot
method: 'get',
data: parameter,
header: {
headers: { 'Content-Type': 'application/x-download' }
},
responseType: 'blob'
})
}
后端代码第一种 这种可以指定表格内容和顺序 小数据量推荐
public static void downloadExcel1(List<Map<String, Object>> list, HttpServletResponse response) {
Workbook workbook = new XSSFWorkbook();
CellStyle cellStyle = workbook.createCellStyle();
// 设置这些样式
cellStyle.setBorderBottom(BorderStyle.THIN);
cellStyle.setBorderLeft(BorderStyle.THIN);
cellStyle.setBorderRight(BorderStyle.THIN);
cellStyle.setBorderTop(BorderStyle.THIN);
Sheet sheet1 = workbook.createSheet("表格");
/* 创建第一行 标题行 start ------------- */
Row sheet1Row = sheet1.createRow(0);
//创建第一列(呈批号)
String data[]={"控制点","测评项","测评方法及步骤","现场记录","结果判断","整改建议"};
for(int i=0;i<data.length;i++){
Cell sheet1RowCell0 = sheet1Row.createCell(i);
sheet1RowCell0.setCellType(CellType.STRING);
sheet1RowCell0.setCellValue(data[i]);
}
int i=0;
for (Map<String, Object> map : list) {
Row dataRow = sheet1.createRow(i + 1);
//订单编号
Cell dataRowCell0 = dataRow.createCell(0);
dataRowCell0.setCellType(CellType.STRING);
dataRowCell0.setCellValue((String) map.get(data[0]));
Cell dataRowCell1 = dataRow.createCell(1);
dataRowCell1.setCellType(CellType.STRING);
dataRowCell1.setCellValue((String) map.get(data[1]));
Cell dataRowCell2 = dataRow.createCell(2);
dataRowCell2.setCellType(CellType.STRING);
dataRowCell2.setCellValue((String) map.get(data[2]));
Cell dataRowCell3 = dataRow.createCell(3);
dataRowCell3.setCellType(CellType.STRING);
dataRowCell3.setCellValue((String) map.get(data[3]));
Cell dataRowCell4 = dataRow.createCell(4);
dataRowCell4.setCellType(CellType.STRING);
dataRowCell3.setCellValue((String) map.get(data[4]));
Cell dataRowCell5 = dataRow.createCell(5);
dataRowCell5.setCellType(CellType.STRING);
dataRowCell5.setCellValue((String) map.get(data[5]));
i++;
}
try {
response.setContentType("application/binary;charset=utf-8");
response.setHeader("Content-disposition", "attachment; filename=" + new String("df".getBytes("gb2312"), "ISO8859-1") + ".xlsx");
response.setCharacterEncoding("utf-8");
ServletOutputStream outputStream = response.getOutputStream();
workbook.write(outputStream);
outputStream.flush();
outputStream.close();
} catch (Exception e) {
e.printStackTrace();
} finally {
if (workbook != null) {
try {
workbook.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
第二种数据 数据量列数较大推荐
/**
* 导出excel
*/
public static void downloadExcel(List<Map<String, Object>> list, HttpServletResponse response) throws IOException {
String tempPath = SYS_TEM_DIR + IdUtil.fastSimpleUUID() + ".xlsx";
File file = new File(tempPath);
BigExcelWriter writer = ExcelUtil.getBigWriter(file);
// 一次性写出内容,使用默认样式,强制输出标题
writer.write(list, true);
SXSSFSheet sheet = (SXSSFSheet)writer.getSheet();
//上面需要强转SXSSFSheet 不然没有trackAllColumnsForAutoSizing方法
sheet.trackAllColumnsForAutoSizing();
//列宽自适应
writer.autoSizeColumnAll();
//response为HttpServletResponse对象
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8");
//test.xls是弹出下载对话框的文件名,不能为中文,中文请自行编码
response.setHeader("Content-Disposition", "attachment;filename=file.xlsx");
ServletOutputStream out = response.getOutputStream();
// 终止后删除临时文件
file.deleteOnExit();
writer.flush(out, true);
//此处记得关闭输出Servlet流
IoUtil.close(out);
}
maven依赖
<!--进行上传文件所需要的maven依赖-->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<!-- excel工具 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.0</version>
</dependency>
<dependency>
<groupId>xerces</groupId>
<artifactId>xercesImpl</artifactId>
<version>2.12.2</version>
</dependency>
上面代码大家可以根据依赖引入相关依赖,进行更改,即可。