瀏覽器根據 HTTP 回應標頭的 Content-Type 與 Content-Disposition 決定如何處理內容。透過修改 JSP 頁面指令與加入回應標頭,可讓瀏覽器將 HTML 表格內容視為 Excel 或 Word 檔案下載。
<!-- 輸出 Excel -->
<%@ page contentType="application/vnd.ms-excel;charset=UTF-8" language="java" %>
<!-- 輸出 Word -->
<%@ page contentType="application/vnd.ms-word;charset=UTF-8" language="java" %>
放在輸出任何內容之前:
<%
// Excel
response.setHeader("Content-Disposition", "attachment;filename=report.xls");
// Word
response.setHeader("Content-Disposition", "attachment;filename=report.doc");
%>
<table>)、基本樣式(內嵌 style 屬性)<link>)、所有 JavaScript/VBScript<%@ page contentType="application/vnd.ms-excel;charset=UTF-8"
import="java.sql.*,java.util.*" language="java" %>
<%
response.setHeader("Content-Disposition", "attachment;filename=members_"
+ new java.text.SimpleDateFormat("yyyyMMdd").format(new java.util.Date())
+ ".xls");
%>
<html>
<head>
<meta charset="UTF-8">
<style>
table { border-collapse: collapse; }
th, td { border: 1px solid #ccc; padding: 4px 8px; }
th { background-color: #4472C4; color: white; }
</style>
</head>
<body>
<%
// 資料庫查詢邏輯
Connection conn = DriverManager.getConnection(...);
Statement stmt = conn.createStatement();
ResultSet rs = stmt.executeQuery("SELECT id, name, email, reg_date FROM members ORDER BY id");
%>
<table>
<tr><th>ID</th><th>姓名</th><th>Email</th><th>註冊日期</th></tr>
<%
while (rs.next()) {
%>
<tr>
<td><%=rs.getInt("id")%></td>
<td><%=rs.getString("name")%></td>
<td><%=rs.getString("email")%></td>
<td><%=rs.getString("reg_date")%></td>
</tr>
<%
}
rs.close(); stmt.close(); conn.close();
%>
</table>
</body>
</html>
檔名包含中文時,需處理瀏覽器編碼差異:
String fileName = "會員清單.xls";
String encodedFileName = java.net.URLEncoder.encode(fileName, "UTF-8")
.replaceAll("\\+", "%20"); // 空格處理
response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + encodedFileName);
上述方法產生的是「HTML 偽裝的 .xls」,功能有限。正式專案建議使用 Apache POI 產生真正的二進位 Excel 檔案:
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.3</version>
</dependency>
// Servlet 中產生真正的 .xlsx
Workbook wb = new XSSFWorkbook();
Sheet sheet = wb.createSheet("會員");
Row header = sheet.createRow(0);
header.createCell(0).setCellValue("ID");
header.createCell(1).setCellValue("姓名");
// ... 填入資料
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment;filename=members.xlsx");
wb.write(response.getOutputStream());
POI 的 SXSSFWorkbook 支援串流寫入,適合大量資料匯出。
| 方法 | 優點 | 缺點 | 適用場景 |
|---|---|---|---|
| Content-Type + HTML 表格 | 零依賴、極簡單、快速原型 | 非真實格式、樣式支援弱、大檔案易當機 | 簡單報表、內部工具、資料筆數<1000 |
| Apache POI (HSSF/XSSF) | 真實格式、完整樣式、公式、圖表支援 | 需引入套件、程式碼較多、記憶體佔用大 | 正式專案、複雜報表、客戶交付 |
| POI SXSSF (串流) | 低記憶體、支援超大資料量 | 功能受限(無法讀取已寫入列) | 十萬列以上匯出 |
選擇哪種方式,取決於專案需求與資料規模。快速驗證概念用 HTML 法;正式上線請投資 POI。