需求描述
要求批量導出數據,以excel
的格式。
選擇方式
前臺 + 後臺
之前在別的項目中也遇到過導出的問題,解決方式是直接在前臺導出將表格導出。
這次沒有選擇前臺導出的方式,是由於需要導出所有的數據,所以考慮直接在後臺獲取所有的數據,然後就直接導出,最後前臺觸發導出API。
後臺實現
導出使用的是POI
,在上一篇文章中,我已做了基本的介紹,這裏就不做介紹配置了,參照:POI實現將導入Excel文件
創建表格
首先先建立一張表,這裏要建立.xlsx
格式的表格,使用XSSFWorkbook
:
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("new sheet");
接着創建表格的行
和單元格
:
Row row = sheet.createRow(0);
row.createCell(0);
然後設置表頭
:
row.createCell(0).setCellValue("學號");
row.createCell(1).setCellValue("姓名");
row.createCell(2).setCellValue("手機號碼");
最後獲取所有的數據,對應的填寫
到單元格中:
int i = 1;
for (Student student : studentList) {
row = sheet.createRow(i);
row.createCell(0).setCellValue(student.getStudentNumber());
row.createCell(1).setCellValue(student.getName());
row.createCell(2).setCellValue(student.getPhoneNumber());
i++;
}
輸出
這部分是糾結比較久的,反覆試了很多次。
一開始是直接以文件輸出流的形式輸出的:
FileOutputStream output = new FileOutputStream("test.xlsx");
workbook.write(output);
這樣可以正確生成文件,但是問題是,它會生成在項目的根目錄
下。
而我們想要的效果是,下載在本地
自己的文件夾中。
要解決這個問題,需要添加相應信息,返回給瀏覽器:
OutputStream fos = response.getOutputStream();
response.reset();
String fileName = "test";
fileName = URLEncoder.encode(fileName, "utf8");
response.setHeader("Content-disposition", "attachment;filename="+ fileName+".xlsx");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
workbook.write(fos);
fos.close();
後臺完成代碼:
public void batchExport(HttpServletResponse response) {
logger.debug("創建工作表");
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("new sheet");
logger.debug("獲取所有學生");
List<Student> studentList = (List<Student>) studentRepository.findAll();
logger.debug("建立表頭");
Row row = sheet.createRow(0);
row.createCell(0).setCellValue("學號");
row.createCell(1).setCellValue("姓名");
row.createCell(2).setCellValue("手機號碼");
logger.debug("將學生信息寫入對應單元格");
int i = 1;
for (Student student : studentList) {
row = sheet.createRow(i);
row.createCell(0).setCellValue(student.getStudentNumber());
row.createCell(1).setCellValue(student.getName());
row.createCell(2).setCellValue(student.getPhoneNumber());
i++;
}
OutputStream fos;
try {
fos = response.getOutputStream();
response.reset();
String fileName = "test";
fileName = URLEncoder.encode(fileName, "utf8");
response.setHeader("Content-disposition", "attachment;filename="+ fileName+".xlsx");
response.setCharacterEncoding("UTF-8");
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");// 設置contentType爲excel格式
workbook.write(fos);
fos.close();
} catch (Exception e) {
e.printStackTrace();
}
}
前臺實現
在前臺調用的時候,也經歷了多次失敗,google了很多篇文章,各種各樣的寫法都有,自己也是試了試,前臺後臺都對照做了很多嘗試,但基本都是有問題的。這裏我值給出我最後選擇配套後臺的方法。
// 後臺導出路由
const exportUrl = '/api/student/batchExport';
// 創建a標籤,並點擊
let a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display:none');
a.setAttribute('href', exportUrl);
a.click();
URL.revokeObjectURL(exportUrl);
最後的實現還是一種比較簡單的方法,創建了一個a標籤
,然後隱式點擊。
注意到這裏我沒有使用http
請求,主要是他並不能觸發瀏覽器的下載,在發起請求後,並沒有正確的生成文件,具體是什麼還不清楚。後面弄明白後我會再更新這篇文章。
總結
我們在google的時候,很多時候,我們並不能一下子就找到我們想要的東西,但是並不是說這在做無用功,因爲我們往往會在一些類似的文章中找到靈感。
所以,當我們沒有直接找到我們想要的結果的時候,不妨大膽的做一些嘗試,因爲我們會在一次又一次失敗的嘗試中,慢慢的瞭解問題的原理到底是怎麼回事。
相關參考:
https://my.oschina.net/u/3644...
https://blog.csdn.net/LUNG108...