CREATE TABLE tblBooksUpload (
DocID INT IDENTITY PRIMARY KEY,
DocTitle VARCHAR(200),
Doc IMAGE, -- 二進位檔案內容
DocType VARCHAR(50), -- 副檔名/MIME 類型,供瀏覽器正確呈現
EntryDate DATETIME DEFAULT GETDATE()
);
CREATE PROCEDURE usp_BooksUploadFile
@Title VARCHAR(200),
@Doc IMAGE,
@DocType VARCHAR(4)
AS
INSERT INTO tblBooksUpload (DocTitle, Doc, DocType)
VALUES (@Title, @Doc, @DocType);
<form id="frmUpload" method="post" enctype="multipart/form-data" runat="server">
<asp:TextBox ID="txtTitle" runat="server" />
<asp:RequiredFieldValidator ControlToValidate="txtTitle" ErrorMessage="* 標題必填" runat="server" />
<input id="fuFile" type="file" runat="server" />
<asp:Button ID="btnSubmit" runat="server" Text="上傳" OnClick="btnSubmit_Click" />
</form>
protected void btnSubmit_Click(object sender, EventArgs e)
{
if (!Page.IsValid || fuFile.PostedFile == null || fuFile.PostedFile.ContentLength == 0)
return;
// 1. 判斷副檔名對應 DocType
string ext = Path.GetExtension(fuFile.PostedFile.FileName).ToLower();
string docType = ext switch
{
".doc" => "doc", ".docx" => "docx",
".pdf" => "pdf",
".jpg" or ".jpeg" => "jpg",
".png" => "png",
".gif" => "gif",
_ => "bin"
};
// 2. 讀取檔案到位元組陣列
int len = fuFile.PostedFile.ContentLength;
byte[] buffer = new byte[len];
using (Stream s = fuFile.PostedFile.InputStream)
s.Read(buffer, 0, len);
// 3. 參數化寫入資料庫
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["Books"].ConnectionString))
using (SqlCommand cmd = new SqlCommand("usp_BooksUploadFile", conn))
{
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.Add("@Title", SqlDbType.VarChar, 200).Value = txtTitle.Text;
cmd.Parameters.Add("@Doc", SqlDbType.Image).Value = buffer;
cmd.Parameters.Add("@DocType", SqlDbType.VarChar, 4).Value = docType;
conn.Open();
cmd.ExecuteNonQuery();
}
lblMsg.Text = "上傳成功";
}
Download.ashx 一般處理常式,依 DocID 查詢資料庫,Response.ContentType = row["DocType"],Response.BinaryWrite((byte[])row["Doc"])。<img src="Download.ashx?id=123" /> 顯示。FILESTREAM / FileTable (SQL Server 2012+) 避免記憶體壓力。| 優點 | 缺點 |
|---|---|
| 檔案與資料庫交易一致性(備份/還原單一 .bak) | 資料庫體積快速膨脹,備份/還原耗時 |
| 權限控管集中在資料庫層級 | 讀取需經由程式碼,無法直接靜態連結/CDN 加速 |
| 刪除參考即刪除檔案,無孤兒檔 | 大量二進位資料影響緩衝池效能 |
建議:小檔(文件、圖示)可存資料庫;大檔(影片、備份)存檔案系統/雲端儲存,資料庫僅存路徑。