將 DataTable 資料導出為 Excel 檔案(.xls)是常見需求。本方案採用 DataGrid 渲染 HTML 表格,再透過 HttpResponse 輸出檔案流,支援中文檔名編碼、大檔案分塊傳輸與臨時檔清理。
///
/// 將 DataTable 導出為 Excel 檔案並提供下載
///
/// 當前 Page 實例(取得 Response/Server)
/// 要導出的 DataTable
/// 下載檔名(含 .xls 副檔名)
public static void ExportToExcel(System.Web.UI.Page page, System.Data.DataTable dt, string fileName) {
HttpResponse response = page.Response;
// 1. 使用 DataGrid 渲染 HTML 表格
System.Web.UI.WebControls.DataGrid dg = new System.Web.UI.WebControls.DataGrid();
dg.DataSource = dt.DefaultView;
dg.AllowPaging = false; // 關閉分頁,導出全部數據
dg.HeaderStyle.BackColor = System.Drawing.Color.Green;
dg.HeaderStyle.HorizontalAlign = HorizontalAlign.Center;
dg.HeaderStyle.Font.Bold = true;
dg.DataBind();
// 2. 設定 HTTP 標頭:檔案下載、編碼、Content-Type
response.Clear();
response.Buffer = true;
response.Charset = "GB2312"; // 舊版 Excel 相容性較好
response.AppendHeader("Content-Disposition",
"attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8));
response.ContentEncoding = System.Text.Encoding.GetEncoding("GB2312");
response.ContentType = "application/ms-excel";
// 3. 將 DataGrid 渲染至 StringWriter
System.IO.StringWriter sw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter(sw);
dg.RenderControl(hw);
// 4. 可選:存檔至伺服器臨時路徑(若需二次處理)
string tempPath = page.Server.MapPath("~/Files/") + fileName;
System.IO.Directory.CreateDirectory(page.Server.MapPath("~/Files/"));
System.IO.File.WriteAllText(tempPath, sw.ToString(), System.Text.Encoding.GetEncoding("GB2312"));
// 5. 分塊輸出檔案流至客戶端(支援大檔案)
DownloadFile(response, fileName, tempPath);
response.End();
}
private static bool DownloadFile(HttpResponse response, string fileName, string fullPath) {
try {
response.ContentType = "application/octet-stream";
response.AppendHeader("Content-Disposition",
"attachment;filename=" + HttpUtility.UrlEncode(fileName, System.Text.Encoding.UTF8) + ";charset=GB2312");
using (System.IO.FileStream fs = System.IO.File.OpenRead(fullPath)) {
long fileSize = fs.Length;
int bufferSize = 102400; // 100KB 緩衝區
byte[] buffer = new byte[bufferSize];
long pos = 0;
while (pos < fileSize) {
int readSize = (int)Math.Min(bufferSize, fileSize - pos);
if (readSize < bufferSize) buffer = new byte[readSize]; // 最後一塊調整大小
fs.Read(buffer, 0, readSize);
response.BinaryWrite(buffer);
response.Flush(); // 關鍵:立即輸出,避免大檔案記憶體壓力
pos += readSize;
}
}
// 6. 清理臨時檔
if (System.IO.File.Exists(fullPath)) System.IO.File.Delete(fullPath);
return true;
}
catch {
return false;
}
}
| 環節 | 處理方式 | 說明 |
|---|---|---|
| 中文檔名 | HttpUtility.UrlEncode(fileName, Encoding.UTF8) | 避免瀏覽器下載時檔名亂碼 |
| 內容編碼 | ContentEncoding = Encoding.GetEncoding("GB2312") | Excel 97-2003 相容性最佳;新版可用 UTF-8+BOM |
| 大檔案支援 | 分塊讀取 + Response.Flush() | 避免大數據一次載入記憶體導致 OOM |
| 臨時檔清理 | File.Delete() 在傳輸完成後 | 防止伺服器磁碟佔用 |
| 渲染方式 | DataGrid.RenderControl() | 利用內建控制項產生標準 HTML 表格,Excel 可直接開啟 |
SheetJS (xlsx.js) + FileSaver.js,將導出邏輯移至客戶端,減輕伺服器壓力。ContentType 為 application/ms-excel,且內容為 HTML 表格非二進位 Excel 格式。ContentEncoding 與檔案實際編碼一致(GB2312/UTF-8)。httpRuntime executionTimeout 或改用分批導出/背景作業。