下載
vue
這里可能會出現的一個問題是,無法獲取到文件名,需要springboot在響應頭上將content-disposition暴露出來
let fileName = decodeURI(res.headers['content-disposition']);// 設置文件名
即:
response.addHeader("Access-Control-Expose-Headers", "Content-disposition");
之前將content-disposition暴露出來,在js中也無法通過res.headers['Content-disposition']獲取文件名,需要修改成小寫的content-disposition
download() {
axios({
method: 'post',// 設置請求方式
url: `http://localhost:8001/attendance2/exportAttendance`,// 設置請求地址
data: this.exportForm,
responseType: 'blob'
}).then(function (res) {
// 得到請求到的數據后,對數據進行處理
let blob = new Blob([res.data], {type: 'application/vnd.ms-excel;charset=utf-8'});// 創建一個類文件對象:Blob對象表示一個不可變的、原始數據的類文件對象
let fileName = decodeURI(res.headers['content-disposition']);// 設置文件名稱,decodeURI:可以對后端使用encodeURI() 函數編碼過的 URI 進行解碼。encodeURI() 是后端為了解決中文亂碼問題
// console.log(fileName)
if (fileName) {// 根據后端返回的數據處理文件名稱
fileName = fileName.substring(fileName.indexOf('=') + 1);
}
const link = document.createElement('a')// 創建一個a標簽
link.download = fileName;// 設置a標簽的下載屬性
link.style.display = 'none';// 將a標簽設置為隱藏
link.href = URL.createObjectURL(blob);// 把之前處理好的地址賦給a標簽的href
document.body.appendChild(link);// 將a標簽添加到body中
link.click();// 執行a標簽的點擊方法
URL.revokeObjectURL(link.href) // 下載完成釋放URL 對象
document.body.removeChild(link)// 移除a標簽
})
},
EasyExcel
Controller:
@ApiOperation(value = "導出考勤信息")
@PostMapping("exportAttendance")
public void exportAttendance(HttpServletResponse response, @RequestBody ExportForm exportForm){
// System.out.println(exportForm.toString());
try {
service.downloadAttendance(response, exportForm);
} catch (IOException e) {
e.printStackTrace();
}
}
Service:
這里關鍵點的地方有以下幾個:
-
響應頭設置:
response.setHeader("Content-disposition", "attachment;filename=attendance.xlsx"); response.addHeader("Access-Control-Expose-Headers", "Content-disposition"); // 設置response的內容類型為MicroSoft-excel response.setContentType("application/vnd.ms-excel");
-
通過EasyExcel寫入多個sheet
// 寫入考勤記錄sheet WriteSheet writeSheet = EasyExcel.writerSheet(0, "考勤記錄") .head(WriteAttendanceData.class) .build(); excelWriter.write(getAttendance(exportForm, workerDb), writeSheet); // 寫入加班記錄sheet writeSheet = EasyExcel.writerSheet(1, "加班記錄") .head(WriteExtraData.class) .build(); excelWriter.write(getExtras(exportForm, workerDb), writeSheet); // 寫入請假記錄sheet writeSheet = EasyExcel.writerSheet(2, "請假記錄") .head(WriteLeaveData.class) .build(); excelWriter.write(getLeaves(exportForm, workerDb), writeSheet); //寫完之后關閉流 excelWriter.finish();
WriteAttendanceData是自定義的類
@Data public class WriteAttendanceData { @ExcelProperty("員工姓名") private String workerName; @ExcelProperty("員工賬號") private String workerAccount; @ExcelProperty("考勤備注") private String note; @ExcelProperty("上班時間") private Date startTime; @ExcelProperty("下班時間") private Date endTime; }
-
從數據庫獲取數據
private List<WriteExtraData> getExtras(ExportForm exportForm, Worker worker) { QueryWrapper<Extra> extraQueryWrapper = new QueryWrapper<>(); extraQueryWrapper.eq("worker_id", worker.getId()); extraQueryWrapper.between("extra_time", exportForm.getStartTime(), exportForm.getEndTime()); List<Extra> extras = extraService.list(extraQueryWrapper); List<WriteExtraData> writeExtraDataList = new ArrayList<>(); // 整理數據 for (Extra extra: extras){ String name = worker.getName(); String account = worker.getAccount(); String note = extra.getNote(); Date extraTime = extra.getExtraTime(); Double extraLength = extra.getExtraLength(); WriteExtraData extraData = new WriteExtraData( name, account, note, extraTime, extraLength ); writeExtraDataList.add(extraData); } return writeExtraDataList; }