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

使用 ADO.NET 在 SQL Server 中儲存與讀取大型二進位檔案

     編輯:更多程式設計知識

前言

在實際開發中,我們經常需要將圖片、可執行檔、影片、文件等大型二進位物件存入資料庫。Microsoft SQL Server 提供了 image 資料類型,可儲存高達 2 GB 的二進位資料。本文將示範如何透過 ADO.NET 搭配 SQL Server,實作檔案的寫入、讀取與另存新檔功能。

建立測試資料表

請在查詢分析器中執行以下 T-SQL 指令,建立名為 imgtable 的資料表:

CREATE TABLE [imgtable] (
    [imgid] [int] IDENTITY(1,1) NOT NULL,
    [imgname] [varchar](100) COLLATE Chinese_PRC_CI_AS NULL,
    [imgData] [image] NULL,
    PRIMARY KEY CLUSTERED ([imgid]) ON [PRIMARY]
) ON [PRIMARY] TEXTIMAGE_ON [PRIMARY]

執行完成後,所選資料庫中將會多出一個 imgtable 資料表,包含自動遞增的識別碼、檔案名稱與二進位資料欄位。

完整的 Windows Forms 範例程式

以下是一個完整的 C# Windows Forms 範例,包含三個按鈕:

  • 開啟檔案並存入資料庫:透過 OpenFileDialog 選取檔案,讀取位元組陣列後以參數化 SQL 寫入。
  • 從資料庫讀取圖片並顯示:查詢符合條件的記錄,將 image 欄位轉為 MemoryStream 再建構 Bitmap 顯示於 PictureBox。
  • 讀取檔案並存檔開啟:將資料庫中的二進位資料寫入暫存檔,再用 Process.Start 呼叫系統關聯程式開啟。

關鍵程式碼片段

儲存檔案至資料庫

private void openFileDialog1_FileOk(object sender, CancelEventArgs e) {
    string filename = openFileDialog1.FileName;
    using (SqlConnection conn = new SqlConnection("server=192.168.2.200;integrated security=sspi;database=northwind"))
    using (SqlCommand cmd = new SqlCommand("INSERT INTO imgtable VALUES (@imgname, @imgData)", conn)) {
        cmd.Parameters.Add("@imgname", SqlDbType.VarChar, 100).Value = filename;
        var pmImg = cmd.Parameters.Add("@imgData", SqlDbType.Image);
        
        byte[] fileData;
        using (FileStream fs = new FileStream(filename, FileMode.Open)) {
            fileData = new byte[fs.Length];
            fs.Read(fileData, 0, fileData.Length);
        }
        pmImg.Value = fileData;
        
        conn.Open();
        try { cmd.ExecuteNonQuery(); }
        catch (Exception ex) { MessageBox.Show(ex.Message); }
    }
}

讀取圖片並顯示

private void button2_Click(object sender, EventArgs e) {
    using (SqlConnection conn = new SqlConnection("server=192.168.2.200;integrated security=sspi;database=northwind"))
    using (SqlCommand cmd = new SqlCommand("SELECT * FROM imgtable WHERE imgname LIKE '%bmp%'", conn)) {
        conn.Open();
        using (SqlDataReader dr = cmd.ExecuteReader()) {
            if (dr.Read()) {
                var sb = dr.GetSqlBinary(2); // 或 (byte[])dr[2]
                using (MemoryStream ms = new MemoryStream(sb.Value)) {
                    pictureBox1.Image = new Bitmap(Bitmap.FromStream(ms));
                }
            }
        }
    }
}

將資料庫檔案另存並開啟

private void button3_Click(object sender, EventArgs e) {
    using (SqlConnection conn = new SqlConnection("server=192.168.2.200;integrated security=sspi;database=northwind"))
    using (SqlCommand cmd = new SqlCommand("SELECT * FROM imgtable WHERE imgname LIKE '%doc'", conn)) {
        conn.Open();
        using (SqlDataReader dr = cmd.ExecuteReader()) {
            if (dr.Read()) {
                var sb = dr.GetSqlBinary(2);
                string filename = @"C:\" + Path.GetFileName(dr.GetString(1));
                File.WriteAllBytes(filename, sb.Value);
                Process.Start(filename);
            }
        }
    }
}

大型檔案處理提醒

上述範例將整個檔案一次讀入記憶體陣列,適用於小型檔案。若檔案大小超過實體記憶體,或為超大型檔案(如影片),必須改用 分塊讀寫(Chunked I/O):

  • 使用 FileStream 搭配固定大小緩衝區(如 8KB~64KB)分段讀取。
  • 搭配 SQL Server 的 UPDATETEXT 或 .WRITE 子句分段寫入 image/varbinary(max) 欄位。
  • 或改用 FileStream / FileTable(SQL Server 2012+)將檔案存放於檔案系統,資料庫僅存路徑。

此外,實務上建議:

  1. 使用 using 區塊確保連線、資料流正確釋放。
  2. 連線字串應存放於設定檔(app.config/web.config),勿硬編碼。
  3. 參數化查詢已防止 SQL Injection,但仍需驗證檔案副檔名、大小與 MIME 類型。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved