using System;
using System.Data.SqlClient;
using System.IO;
using System.Windows.Forms;
namespace ImageToDbDemo {
public partial class MainForm : Form {
private const string ConnStr =
"Server=.;Database=TestDb;Trusted_Connection=True;";
public MainForm() { InitializeComponent(); }
private void btnSelectAndSave_Click(object sender, EventArgs e) {
using (var ofd = new OpenFileDialog()) {
ofd.Filter = "圖片文件|*.jpg;*.jpeg;*.png;*.bmp;*.gif|所有文件|*.*";
ofd.Title = "選擇要存入數據庫的圖片";
if (ofd.ShowDialog() != DialogResult.OK) return;
string filePath = ofd.FileName; // ① 獲取完整路徑
byte[] imageBytes = File.ReadAllBytes(filePath); // ② 讀取二進制
SaveToDatabase(filePath, imageBytes); // ③ 入庫
MessageBox.Show($"已存入:{Path.GetFileName(filePath)} ({imageBytes.Length} bytes)");
}
}
private void SaveToDatabase(string fileName, byte[] data) {
const string sql = @"
INSERT INTO Images (FileName, ContentType, Data, UploadTime)
VALUES (@FileName, @ContentType, @Data, GETDATE())";
using (var conn = new SqlConnection(ConnStr))
using (var cmd = new SqlCommand(sql, conn)) {
cmd.Parameters.Add("@FileName", System.Data.SqlDbType.NVarChar, 255).Value = fileName;
cmd.Parameters.Add("@ContentType", System.Data.SqlDbType.NVarChar, 50).Value = GetMimeType(fileName);
cmd.Parameters.Add("@Data", System.Data.SqlDbType.VarBinary, -1).Value = data; // -1 = MAX
conn.Open();
cmd.ExecuteNonQuery();
}
}
private string GetMimeType(string fileName) {
string ext = Path.GetExtension(fileName).ToLowerInvariant();
return ext switch {
".jpg" or ".jpeg" => "image/jpeg",
".png" => "image/png",
".bmp" => "image/bmp",
".gif" => "image/gif",
_ => "application/octet-stream"
};
}
}
}
CREATE TABLE Images (
Id INT IDENTITY(1,1) PRIMARY KEY,
FileName NVARCHAR(255) NOT NULL,
ContentType NVARCHAR(50) NOT NULL,
Data VARBINARY(MAX) NOT NULL, -- 關鍵:MAX 支持 2GB
UploadTime DATETIME DEFAULT GETDATE()
);
CREATE INDEX IX_Images_FileName ON Images(FileName);
private void btnLoad_Click(object sender, EventArgs e) {
using (var conn = new SqlConnection(ConnStr))
using (var cmd = new SqlCommand("SELECT FileName, ContentType, Data FROM Images WHERE Id=@Id", conn)) {
cmd.Parameters.AddWithValue("@Id", txtId.Text);
conn.Open();
using (var reader = cmd.ExecuteReader()) {
if (reader.Read()) {
string name = reader.GetString(0);
string mime = reader.GetString(1);
byte[] data = (byte[])reader[2]; // 直接讀取 byte[]
// 保存到臨時文件並打開
string tempPath = Path.Combine(Path.GetTempPath(), name);
File.WriteAllBytes(tempPath, data);
Process.Start(new ProcessStartInfo(tempPath) { UseShellExecute = true });
}
}
}
}
| 技術 | 作用 |
|---|---|
| `FileStream` + `SqlFileStream` (Filestream) | 文件存文件系統,DB 只存指針,突破 2GB 限制 |
| 分塊上傳 | 前端分片、後端合併,避免 LOH 內存碎片 |
| 異步 `ReadAllBytesAsync` / `ExecuteNonQueryAsync` | 不阻塞 UI 線程 |
| 壓縮 (GZip/Deflate) | 節省存儲與傳輸帶寬 |
`OpenFileDialog.FileName` 即路徑,`File.ReadAllBytes` 即二進制,`SqlDbType.VarBinary` 配合參數化 SQL 即入庫。**三行核心代碼,其餘皆是工程化細節**(異常處理、大文件優化、安全配置)。掌握這條主線,圖片/文件存數據庫不再是難題。