首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 網頁程式設計 >> JSP 程式設計 >> 關於JSP

JSP動態輸出Excel解決方案:JExcelApi實戰與中文亂碼徹底解決

     編輯:關於JSP

Web系統導出Excel是高頻需求。Apache POI雖強大但體積大、API複雜。JExcelApi (jxl.jar)輕量、API直觀、專注Excel讀寫,是中小項目導出功能的優選。本文演示從JavaBean到JSP的完整導出鏈路,並徹底解決中文亂碼與響應頭衝突問題。

依賴準備

下載jxl.jar(官網),放入WEB-INF/lib或Maven:

<dependency>
    <groupId>net.sourceforge.jexcelapi</groupId>
    <artifactId>jxl</artifactId>
    <version>2.6.12</version>
</dependency>

JavaBean:純導出邏輯

package com.jagie.test;

import java.io.OutputStream;
import jxl.*;
import jxl.write.*;
import jxl.format.*;
import java.awt.Color;

public class ExcelExporter {
    public static void writeExcel(OutputStream os) throws Exception {
        WritableWorkbook wwb = Workbook.createWorkbook(os);
        WritableSheet ws = wwb.createSheet("TestSheet1", 0);

        // 普通單元格(中文無亂碼,JExcelApi內部UTF-16LE編碼)
        Label labelC = new Label(0, 0, "我愛中國");
        ws.addCell(labelC);

        // 樣式單元格:字體、粗體、顏色、背景
        WritableFont wfc = new WritableFont(WritableFont.ARIAL, 20, WritableFont.BOLD, false,
                UnderlineStyle.NO_UNDERLINE, Colour.GREEN);
        WritableCellFormat wcfFC = new WritableCellFormat(wfc);
        wcfFC.setBackground(Colour.RED);
        labelC = new Label(6, 0, "中國愛我", wcfFC);
        ws.addCell(labelC);

        wwb.write();
        wwb.close(); // 必須close釋放資源
    }

    // 單元測試入口
    public static void main(String[] args) throws Exception {
        writeExcel(new java.io.FileOutputStream("test.xls"));
    }
}

JSP導出入口:關鍵三步

<%@ page import="com.jagie.test.ExcelExporter" %>
<%
    // 1. 重置響應:清除容器可能預寫的內容(如JSP模板空白、錯誤頁片段)
    response.reset();

    // 2. 設置正確Content-Type:瀏覽器識別為Excel觸發下載/打開
    response.setContentType("application/vnd.ms-excel");
    // 建議添加Content-Disposition指定文件名
    response.setHeader("Content-Disposition", "attachment; filename=export.xls");

    // 3. 直接寫入Servlet輸出流
    ExcelExporter.writeExcel(response.getOutputStream());
%>

為什麼response.reset()不可省略?

JSP編譯後的Servlet會在_jspService開頭隱式寫入模板文本(換行、空白)。若不reset(),這些字節會混入Excel二進制流,導致文件損壞打不開。凡是二進制輸出(Excel/PDF/圖片/Zip),JSP頁面必須response.reset()開頭。

關於page指令contentType的誤區

若在JSP頂部寫:

<%@ page contentType="application/vnd.ms-excel;charset=GBK" %>

容器生成的Servlet會先response.setContentType(...charset=GBK),隨後你的代碼response.reset()會清除該頭,但隨後out.print()模板文本時,容器可能再次隱式設置Content-Type,導致響應頭混亂。結論:二進制導出頁面,不要用page指令設置Content-Type,完全由代碼控制。

中文亂碼根因與對策

  • JExcelApi內部使用UTF-16LE寫入BIFF格式,不涉及字符編碼轉換,Java String直接寫入,**天然無中文亂碼**。
  • 亂碼通常源於:response.getOutputStream()前已有字符輸出(out.print())、或Content-Type缺失導致瀏覽器誤判編碼。
  • 大文件導出建議:設置response.setBufferSize(65536)、啟用response.setHeader("Content-Length", ...)(需預計算或分塊寫入臨時文件)。

現代化替代:Apache POI (SXSSF)

JExcelApi僅支持舊版.xls(BIFF8,65536行限制)。大數據量、.xlsx格式、流式寫入需遷移至POI SXSSFWorkbook(低內存流式):

SXSSFWorkbook wb = new SXSSFWorkbook(100); // 保留100行內存,其餘刷盤
Sheet sh = wb.createSheet();
Row row = sh.createRow(0);
row.createCell(0).setCellValue("大數據導出無壓力");
wb.write(response.getOutputStream());
wb.dispose(); // 釋放臨時文件

選對工具、控制響應頭、隔離模板輸出——三板斧搞定JSP導出Excel全場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved