在使用kendoui的Grid導出Excel報表的過程中出現的幾個問題:
1、在打開下載好的文檔時會出現警告
2、打開Excel時,發現Excel的列是緊湊的,不能保證正常的表格的寬度
目前上述問題,我還沒找到問題是如何發生的,且沒有合適的解決辦法(猜測是由于JsZip庫導致的該類型問題)
因此,我希望能將Excel報表的導出放到服務器上去完成!
POI:Apache旗下的一個開源函式庫,提供了 API 給 Java 對 Microsoft Office 格式檔案讀和寫的功能;
結構:
對應POI文檔:http://tool.oschina.net/apidocs/apidoc?api=apache-POI (咳咳。我這里不知道為什么官網進不去!所以只提供鏡像鏈接!官網傳送門)
接下來以xlsx文件為例展示來做一個輸出的流程;
因為要在通過瀏覽器端和服務端交互做導出表格的工作,那么就應該是在瀏覽器端發送請求后,服務器做出響應,在響應中增加要導出報表的相關信息;
因為還有其他需求可能會用到這些部分,我將創建導出xlsx文件的操作包裝成了一個根據類,具體請參照代碼;
其中要特別注意火狐瀏覽器,火狐瀏覽器的編碼規則不同與其他瀏覽器的編解碼規則,火狐要求必須使用iso-8859-1進行傳輸信息,直接使用utf8會出現亂碼問題。
import org.apache.poi.openxml4j.exceptions.OpenXML4JRuntimeException;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URLEncoder;
public class ReportUtil {
/**
* 根據傳入的請求和文件名,創建一個輸出流
* @param request 瀏覽器請求,如果請求來判斷當前瀏覽器類型,進行轉碼工作
* @param httpServletResponse 服務端響應,通過響應中的輸出流導出文件
* @param fileName 文件名
* @return 一個響應輸出流
* @throws IOException 在編碼過程中會出現IO異常
*/
public static ServletOutputStream createOutputStream(HttpServletRequest request,HttpServletResponse httpServletResponse, String fileName) throws IOException {
// 通常解決漢字亂碼方法用URLEncoder.encode(...)
String fileNameDisplay = URLEncoder.encode(fileName, "UTF-8") + ".xlsx";
if ("FF".equals(getBrowser(request))) {
// 針對火狐瀏覽器處理方式不一樣了
fileNameDisplay = new String(fileName.getBytes("UTF-8"),
"iso-8859-1") + ".xlsx";
}
httpServletResponse.addHeader("Content-Disposition", "attachment;filename=" + fileNameDisplay);
// httpServletResponse.addHeader("Content-Disposition", "attachment;filename=\"" + URLEncoder.encode(fileName + ".xlsx", "UTF-8") + "\"");
httpServletResponse.setContentType("application/vnd.ms-excel;charset=UTF-8");
httpServletResponse.setHeader("Accept-Ranges", "bytes");
ServletOutputStream outputStream = httpServletResponse.getOutputStream();
return outputStream;
}
/**
* 工作流寫入workbook并關閉當前管控的對應的workbook和輸出流
* @param wb 當前服務器管控的workbook對象,用于輸出的excel
* @param outputStream 需要寫入對應的workbook中的輸出流
* @throws IOException 在寫入workbook時可能會拋出的異常,此異常提交到上一層解決
*/
public static void streamWriteAndClose(XSSFWorkbook wb,ServletOutputStream outputStream) throws IOException{
try{
wb.write(outputStream);
}catch (OpenXML4JRuntimeException e){
System.err.println(e.getMessage());
}
finally {//包裝到finally中保證關閉操作必執行
//關閉流
try{
outputStream.close();
}catch (Exception ose){
System.err.println(ose.getMessage());
}
try{
wb.close();
}
catch (Exception wbe){
System.err.println(wbe.getMessage());
}
}
}
// 以下為服務器端判斷客戶端瀏覽器類型的方法
private static String getBrowser(HttpServletRequest request) {
String UserAgent = request.getHeader("USER-AGENT").toLowerCase();
if (UserAgent != null) {
if (UserAgent.indexOf("msie") >= 0)
return "IE";
if (UserAgent.indexOf("firefox") >= 0)
return "FF";
if (UserAgent.indexOf("safari") >= 0)
return "SF";
}
return null;
}