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

C# 文件與數據庫雙向交互:存取二進制數據完整指南

     編輯:關於C#

一、核心原理

文件存入數據庫本質是:讀取文件為位元組陣列(二進制流) → 寫入數據庫二進制字段。讀取則是反向操作。SQL Server 用 Image 類型(現推薦 VarBinary(MAX)),Access 用 OLE Object。

二、存入文件到 SQL Server

public void SaveFileToSqlServer(string filePath, string tableName, string fieldName, SqlConnection conn) {
    FileInfo fi = new FileInfo(filePath);
    using (FileStream fs = fi.OpenRead()) {
        byte[] buffer = new byte[fs.Length];
        fs.Read(buffer, 0, (int)fs.Length);
        
        using (SqlCommand cmd = new SqlCommand()) {
            cmd.Connection = conn;
            cmd.CommandText = $"INSERT INTO {tableName} ({fieldName}) VALUES (@file)";
            SqlParameter param = new SqlParameter("@file", SqlDbType.VarBinary) { Value = buffer };
            cmd.Parameters.Add(param);
            if (conn.State == ConnectionState.Closed) conn.Open();
            cmd.ExecuteNonQuery();
        }
    }
}

三、存入文件到 Access

public void SaveFileToAccess(string filePath, string tableName, string fieldName, OleDbConnection conn) {
    FileInfo fi = new FileInfo(filePath);
    using (FileStream fs = fi.OpenRead()) {
        byte[] buffer = new byte[fs.Length];
        fs.Read(buffer, 0, (int)fs.Length);
        
        using (OleDbCommand cmd = new OleDbCommand()) {
            cmd.Connection = conn;
            cmd.CommandText = $"INSERT INTO {tableName} ({fieldName}) VALUES (@file)";
            OleDbParameter param = new OleDbParameter("@file", OleDbType.Binary) { Value = buffer };
            cmd.Parameters.Add(param);
            if (conn.State == ConnectionState.Closed) conn.Open();
            cmd.ExecuteNonQuery();
        }
    }
}

四、Web 表單上傳文件直接存庫

public void SaveUploadedFile(HttpPostedFile postedFile, int mailId, string connStr) {
    string sql = "UPDATE t_mail SET attachfilename=@name, attachfile=@file WHERE mailid=@id";
    using (SqlConnection conn = new SqlConnection(connStr))
    using (SqlCommand cmd = new SqlCommand(sql, conn)) {
        string fileName = System.IO.Path.GetFileName(postedFile.FileName);
        cmd.Parameters.Add("@name", SqlDbType.VarChar).Value = fileName;
        cmd.Parameters.Add("@file", SqlDbType.VarBinary);
        
        using (Stream fs = postedFile.InputStream) {
            byte[] buffer = new byte[postedFile.ContentLength];
            fs.Read(buffer, 0, buffer.Length);
            cmd.Parameters["@file"].Value = buffer;
        }
        cmd.Parameters.Add("@id", SqlDbType.Int).Value = mailId;
        conn.Open();
        cmd.ExecuteNonQuery();
    }
}

五、從數據庫讀取並另存為文件

public void ExtractFileFromDb(string tableName, string fieldName, int id, string outputPath, SqlConnection conn) {
    using (SqlCommand cmd = new SqlCommand($"SELECT {fieldName} FROM {tableName} WHERE ID=@id", conn)) {
        cmd.Parameters.Add("@id", SqlDbType.Int).Value = id;
        if (conn.State == ConnectionState.Closed) conn.Open();
        using (SqlDataReader dr = cmd.ExecuteReader()) {
            if (dr.Read()) {
                byte[] fileData = (byte[])dr[0];
                // 關鍵:使用 FileMode.CreateNew 確保新建文件,BinaryWriter 正確寫入二進制
                using (FileStream fs = new FileStream(outputPath, FileMode.CreateNew))
                using (BinaryWriter bw = new BinaryWriter(fs)) {
                    bw.Write(fileData);
                }
            }
        }
    }
}

關鍵修正: 原代碼用 FileInfo.OpenWrite() 可能導致現有文件追加而非覆蓋,改用 FileStream(FileMode.CreateNew) + BinaryWriter 確保正確另存為 Word/Excel/圖片等原始格式。

六、必要命名空間

using System.Data.SqlClient;
using System.Data.OleDb;
using System.IO;

七、最佳實踐提醒

  • 大文件建議分塊讀寫(Read/Write 循環),避免記憶體壓力。
  • 生產環境務必使用參數化查詢防 SQL 注入(示例已體現)。
  • 連接對象用 using 確保釋放。
  • 考慮將大文件存文件系統,數據庫只存路徑,權衡性能與維護性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved