現在大部分的系統都採用前後端分離的方式來實現系統的開發,以前我們實現下載excel的時候,我們直接使用GET的方法的方式直接將數據寫到頁面上,用戶直接下載即可,但是使用前後端分離的方式就不能使用傳統的方式來實現文件的下載,這時候我們就會遇到各種坑,接下來我將帶大家來了解裏面遇到的各種坑以及相應的解決方案。
1、創建後端工程
首先我們創建一個後端的springboot的工程,然後再引入以下的maven依賴:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>4.0.0</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>4.0.0</version>
</dependency>
<!-- swagger插件 -->
<dependency>
<groupId>com.didispace</groupId>
<artifactId>spring-boot-starter-swagger</artifactId>
<version>1.2.0.RELEASE</version>
</dependency>
2、swagger2開啓
接着我們先開啓我們的swagger2的接口測試工具,直接在主入口類上加上以下的註解即可:
@SpringBootApplication
@EnableSwagger2Doc
public class PoiDemoApplication {
public static void main(String[] args) {
SpringApplication.run(PoiDemoApplication.class, args);
}
}
3、編寫測試方法
最後我們創建一個PoiController的測試的類,代碼如下:
@Controller
@RequestMapping("poi")
public class PoiController {
/**
* 功能描述: 正確的下載xlsx的方式
* @param response
* @throws UnsupportedEncodingException
*/
@PostMapping(value = "downloadXlsWright" ,produces = MediaType.APPLICATION_OCTET_STREAM_VALUE )
public void downloadXlsWright(HttpServletResponse response) throws UnsupportedEncodingException {
// 設置當前的xlsx最大長度爲1000行
SXSSFWorkbook wb = new SXSSFWorkbook(1000);
// 設置文件後綴
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String fn = "xlsx" + sdf.format(new Date()).toString() + ".xlsx";
//設置表格名稱
SXSSFSheet sheet = wb.createSheet("sheet1");
// 設置默認的寬度爲30個字符
sheet.setDefaultColumnWidth(30);
SXSSFRow row = sheet.createRow(0);
for (int i = 0; i < 10; i++) {
// 遍歷插入表頭
SXSSFCell cell = row.createCell(i);
cell.setCellValue("測試表頭" + i);
}
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fn, "UTF-8"));
OutputStream os = null;
try {
os = response.getOutputStream();
wb.write(os);
os.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (wb != null) {
wb.dispose();
}
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 功能描述: 錯誤的下載xlsx的方式
* @param response
* @throws UnsupportedEncodingException
*/
@PostMapping("downloadXlsWrong")
public void downloadXlsWrong(HttpServletResponse response) throws UnsupportedEncodingException {
// 設置當前的xlsx最大長度爲1000行
SXSSFWorkbook wb = new SXSSFWorkbook(1000);
// 設置文件後綴
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
String fn = "xlsx" + sdf.format(new Date()).toString() + ".xlsx";
//設置表格名稱
SXSSFSheet sheet = wb.createSheet("sheet1");
// 設置默認的寬度爲30個字符
sheet.setDefaultColumnWidth(30);
SXSSFRow row = sheet.createRow(0);
for (int i = 0; i < 10; i++) {
// 遍歷插入表頭
SXSSFCell cell = row.createCell(i);
cell.setCellValue("測試表頭" + i);
}
response.setHeader("Access-Control-Expose-Headers", "Content-Disposition");
response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode(fn, "UTF-8"));
OutputStream os = null;
try {
os = response.getOutputStream();
wb.write(os);
os.flush();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (wb != null) {
wb.dispose();
}
try {
if (os != null) {
os.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
也許大家發現了這兩個方法唯一不同的地方就是在PostMapping的註解上加了這個配置,這個配置的作用就是告訴請求的接口,你調用我這個接口的時候,我將爲你返回的類型是文件下載的類型,若不設置默認是application/json的類型返回。
produces = MediaType.APPLICATION_OCTET_STREAM_VALUE
4、驗證結果
這時候我們就可以啓動我們的工程,然後用瀏覽器打開以下的地址來驗證我們的結果了。
我們分別響應以上的兩個請求,這時候大家可以看到如下的頁面:
然後我們分別下載上面的兩個xlsx文件,這時候我們使用專門的excel軟件打開這兩個文件,大家會發現downloadXlsWrong這個請求的接口打開的時候回報如下的錯誤:
5、追根溯源
那是什麼原因導致了我們兩個接口一樣的請求導致一個文件可以打開一個文件打不開,這時候我們可以使用F12的方式來看下這兩個請求的區別:
唯一的區別就是在Request Headers上面一個是*/另外一個是application/octest-stream,這兩個的區別就是默認爲/*前端默認認爲是json因此使用文本的方式去處理的數據導致出來的信息已經不是我們需要的信息了,因此最後下載下來的文件無法打開,那麼這一章我們就完成了後端篇的實現,下一篇將爲大家講解前端篇該如何去響應這個請求,同時實現文件的下載,若需要獲取本章的demo例子,大家可以直接掃描我的公衆號,然後回覆【poi-demo-1】就可以拿到本章的源代碼了: