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

ASP.NET UpdatePanel 實現無重整圖片上傳完整教學 (含資料庫儲存與顯示)

     編輯:ASP.NET 基礎

核心難點與解決方案

FileUpload 控制項在 UpdatePanel 非同步回傳中無法取得檔案,因 multipart/form-data 編碼不支援 AJAX 部分更新。解決方法:在 Triggers 中將上傳按鈕設為 PostBackTrigger,強制完整回傳該按鈕點擊事件。

完整實作三層架構

1. 前端頁面 Default.aspx

<%@ 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>

2. 後端邏輯 Default.aspx.cs

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;
        }
    }
}

3. 圖片輸出 Handler ShowImage.ashx

<%@ 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;
}

4. 資料庫建表腳本

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()
);

5. Web.config 連線字串

<connectionStrings>
    <add name="ImgDB" connectionString="Data Source=.;Initial Catalog=TestDB;User ID=sa;Password=123456" />
</connectionStrings>

關鍵技術點總結

關鍵點說明
enctype="multipart/form-data"表單必須設定此編碼,否則無法上傳檔案
PostBackTriggerFileUpload 需完整回傳才能讀取檔案,設定觸發按鈕為 PostBackTrigger
UpdateMode="Conditional"配合 Trigger 精確控制更新範圍
Handler 輸出圖片避免將圖片寫入實體檔案,直接從資料庫串流輸出,支援權限控管
防快取參數?t=Timestamp 確保瀏覽器重新請求最新圖片
參數化查詢防止 SQL Injection,二進位資料用 SqlDbType.VarBinary, -1 (MAX)

進階擴充建議

  • 多圖上傳:FileUpload 支援 AllowMultiple="true" (HTML5),迴圈處理 PostedFiles 集合。
  • 圖片壓縮/縮圖:上傳前用 System.Drawing 或 ImageSharp 壓縮,節省儲存空間。
  • 雲端儲存:改上傳至 Azure Blob / AWS S3,資料庫僅存 URL。
  • 進度條:需配合 AJAX 上傳元件 (如 FineUploader、Plupload) 或 HTML5 XMLHttpRequest Level 2。
  • 安全性:驗證檔案簽名 (Magic Number) 而非僅副檔名,防止偽裝惡意檔案。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved