FileUpload 控制項在 UpdatePanel 非同步回傳中無法取得檔案,因 multipart/form-data 編碼不支援 AJAX 部分更新。解決方法:在 Triggers 中將上傳按鈕設為 PostBackTrigger,強制完整回傳該按鈕點擊事件。
<%@ Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<html><head><title>無重整圖片上傳示範</title></head><body>
<form id="form1" runat="server" enctype="multipart/form-data"> <!-- 關鍵:表單編碼 -->
<asp:ScriptManager ID="ScriptManager1" runat="server" />
<asp:UpdatePanel ID="UpdatePanel1" runat="server" UpdateMode="Conditional">
<ContentTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" Width="300px" />
<asp:Button ID="btnUpload" runat="server" Text="上傳" OnClick="btnUpload_Click" />
<asp:Label ID="lblMsg" runat="server" ForeColor="Red" />
<br /><br />
<asp:Image ID="imgPreview" runat="server" Height="200px" Width="200px"
ImageUrl="~/Images/noimage.png" />
</ContentTemplate>
<Triggers>
<asp:PostBackTrigger ControlID="btnUpload" /> <!-- 關鍵:強制完整回傳 -->
</Triggers>
</asp:UpdatePanel>
</form></body></html>
public partial class _Default : System.Web.UI.Page
{
protected void btnUpload_Click(object sender, EventArgs e)
{
if (!FileUpload1.HasFile)
{
lblMsg.Text = "請選擇圖片檔案";
return;
}
// 1. 驗證檔案類型與大小
string ext = Path.GetExtension(FileUpload1.FileName).ToLower();
string[] allowed = { ".jpg", ".jpeg", ".png", ".gif", ".bmp" };
if (!allowed.Contains(ext))
{
lblMsg.Text = "僅允許 JPG/PNG/GIF/BMP 格式";
return;
}
if (FileUpload1.PostedFile.ContentLength > 2 * 1024 * 1024) // 2MB
{
lblMsg.Text = "檔案大小不可超過 2MB";
return;
}
try
{
// 2. 讀取檔案位元組
byte[] fileBytes = FileUpload1.FileBytes;
// 3. 儲存至資料庫 (二進位欄位)
string connStr = ConfigurationManager.ConnectionStrings["ImgDB"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
// 先清空舊資料 (示範用,實務依需求)
new SqlCommand("DELETE FROM Images", conn).ExecuteNonQuery();
string sql = "INSERT INTO Images (ImageData, ContentType, FileName, UploadTime) " +
"VALUES (@Data, @Type, @Name, @Time)";
using (SqlCommand cmd = new SqlCommand(sql, conn))
{
cmd.Parameters.Add("@Data", SqlDbType.VarBinary, -1).Value = fileBytes;
cmd.Parameters.AddWithValue("@Type", FileUpload1.PostedFile.ContentType);
cmd.Parameters.AddWithValue("@Name", FileUpload1.FileName);
cmd.Parameters.AddWithValue("@Time", DateTime.Now);
cmd.ExecuteNonQuery();
}
}
// 4. 更新預覽圖片 (指向 Handler)
imgPreview.ImageUrl = "~/ShowImage.ashx?t=" + DateTime.Now.Ticks; // 防快取
lblMsg.Text = "上傳成功!";
lblMsg.ForeColor = System.Drawing.Color.Green;
}
catch (Exception ex)
{
lblMsg.Text = "上傳失敗:" + ex.Message;
}
}
}
<%@ WebHandler Language="C#" Class="ShowImage" %>
using System;
using System.Web;
using System.Data.SqlClient;
using System.Configuration;
public class ShowImage : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
string connStr = ConfigurationManager.ConnectionStrings["ImgDB"].ConnectionString;
using (SqlConnection conn = new SqlConnection(connStr))
{
conn.Open();
string sql = "SELECT TOP 1 ImageData, ContentType FROM Images ORDER BY UploadTime DESC";
using (SqlCommand cmd = new SqlCommand(sql, conn))
using (SqlDataReader dr = cmd.ExecuteReader())
{
if (dr.Read())
{
byte[] imgData = (byte[])dr["ImageData"];
string contentType = dr["ContentType"].ToString();
context.Response.ContentType = contentType;
context.Response.BinaryWrite(imgData);
context.Response.End();
}
}
}
}
public bool IsReusable => false;
}
CREATE TABLE Images (
ID INT IDENTITY(1,1) PRIMARY KEY,
ImageData VARBINARY(MAX) NOT NULL,
ContentType NVARCHAR(50) NOT NULL,
FileName NVARCHAR(255),
UploadTime DATETIME DEFAULT GETDATE()
);
<connectionStrings>
<add name="ImgDB" connectionString="Data Source=.;Initial Catalog=TestDB;User ID=sa;Password=123456" />
</connectionStrings>
| 關鍵點 | 說明 |
|---|---|
| enctype="multipart/form-data" | 表單必須設定此編碼,否則無法上傳檔案 |
| PostBackTrigger | FileUpload 需完整回傳才能讀取檔案,設定觸發按鈕為 PostBackTrigger |
| UpdateMode="Conditional" | 配合 Trigger 精確控制更新範圍 |
| Handler 輸出圖片 | 避免將圖片寫入實體檔案,直接從資料庫串流輸出,支援權限控管 |
| 防快取參數 | ?t=Timestamp 確保瀏覽器重新請求最新圖片 |
| 參數化查詢 | 防止 SQL Injection,二進位資料用 SqlDbType.VarBinary, -1 (MAX) |
FileUpload 支援 AllowMultiple="true" (HTML5),迴圈處理 PostedFiles 集合。System.Drawing 或 ImageSharp 壓縮,節省儲存空間。