c# 操作文件存入數據庫(以二進制形式存入)


  在開發的過程中,經常會遇到將文件存入數據庫的形式,一般常用方法是將文件上傳至服務器,數據庫只需保存文件路徑地址即可,但是很多內部window應用並不鏈接網絡都是本地運行服務,那么此時我們存儲文件就需要用到另一種形式,即將文件 FileStream 操作文件流的形式將文件轉為字節存入數據庫,下載時,在對應轉換下載即可。

 

  本次,我們將提供兩種數據庫的操作方式,PostgresSql 和 Sqlite 兩種數據庫的存儲方式。

 

  PostgresSql

  Psql 數據庫提供了存儲字節的類型,即 bytea,所以創建數據庫時,要將對應的字段設置為 bytea

1 CREATE TABLE tb_flypath 
2 (  
3     ID SERIAL PRIMARY KEY ,
4     FileName TEXT NOT NULL,
5     FileContent bytea NOT NULL,
6     CreateTime timestamp(6) NOT NULL DEFAULT CURRENT_TIMESTAMP
7 )

  那么,設置為 bytea 后就可以將文件轉為字節進行存儲了,使用以下代碼

 1         /// <summary>
 2         /// 將文件轉為字節
 3         /// </summary>
 4         /// <param name="path">文件路徑</param>
 5         /// <returns></returns>
 6         public byte[] getContent(string path)
 7         {
 8             System.IO.FileStream fs = new System.IO.FileStream(@path, System.IO.FileMode.Open);
 9             fs.Position = 0;
10             byte[] content = new byte[fs.Length];
11             fs.Read(content, 0, (int)fs.Length);
12             fs.Close();
13             return content;
14         }

  我們直接使用 SQL 語句,將字節轉為字符串存入數據庫

 1         /// <summary>
 2         /// 字節轉字符串
 3         /// </summary>
 4         /// <param name="inputBytes">字節</param>
 5         /// <returns></returns>
 6         public string ByteToString(byte[] inputBytes)
 7         {
 8             StringBuilder temp = new StringBuilder(2048);
 9             foreach (byte tempByte in inputBytes)
10             {
11                 temp.Append(tempByte > 15 ?
12                 Convert.ToString(tempByte, 2) : '0' + Convert.ToString(tempByte, 2));
13             }
14             return temp.ToString();
15         }
16 
17         string bstr = ByteToString(buffer);
18         string insertSql = string.Format(@"INSERT INTO tb_flyPath (FileContent) VALUES ('{0}')", bstr);

  以上就是將文件寫入數據庫的操作,但是,如果采用此方法的話,就會有問題,因為 INSERT SQL 無法識別字節的類型,所以我們是將字符串存入了對應字節類型的字段里。

  那么后續遇到的問題是,下載文件時,無論如何轉換 FileContent 都無法將下載的文件打開,如果是文本的話,則出現的內容為已轉換的二進制數據。

  至於為什么會出現這樣,還沒研究透,歡迎留言。

  所以,我又采取了以下的方式進行數據存儲,使用數據庫 Parameter 參數執行SQL,這種方法可以將你傳入的數據直接轉為對應的類型  DbType.Bytea ,此類型可以傳入字節類型數據進行存儲,使用這種方式后,存入的數據就可以下載后進行轉換使用並打開各種文件了。

 1         /// <summary>
 2         /// 文件存儲入表
 3         /// </summary>
 4         /// <param name="filePath">文件路徑</param>
 5         /// <param name="id">節點ID</param>
 6         /// <returns></returns>
 7         public bool FileInsert(string filePath, string id)
 8         {
 9             string strErrMsg = "";
10             //讀取文件 
11             FileStream fs = File.OpenRead(filePath);
12             byte[] buffer = new byte[fs.Length];
13             fs.Read(buffer, 0, buffer.Length);
14 
15             if (!CreateCommand(out strErrMsg))
16                 return false;
17 
31             NpgsqlParameter paramFileContent = _Command.CreateParameter();
32             paramFileContent.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Bytea;
33             paramFileContent.ParameterName = "FileContent";
34             paramFileContent.Direction = ParameterDirection.Input;
35             paramFileContent.Value = buffer;
36             _Command.Parameters.Add(paramFileContent);
37 
38             NpgsqlParameter paramFileName = _Command.CreateParameter();
39             paramFileName.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar;
40             paramFileName.ParameterName = "FileName";
41             paramFileName.Direction = ParameterDirection.Input;
42             paramFileName.Value = id;
43             _Command.Parameters.Add(paramFileName);
44 
45             string sqlInsert = "INSERT INTO tb_flypath (filename,filecontent) VALUES (:FileName, :FileContent)";
46             _Command.CommandText = sqlInsert;
47             _Command.CommandType = CommandType.Text;
48 
49             _Connection.Open();
50             int result = _Command.ExecuteNonQuery();
51             _Connection.Close();
52 
53             return result > 0 ? true : false;
54         }
55 
56         /// <summary> 
57         /// 根據文件名從數據庫中獲取文件 
58         /// </summary> 
59         /// <param name="fileName">數據庫中的文件名</param> 
60         /// <param name="savePath">文件的保存路徑,包括文件名,如D:\test.fly</param> 
61         public bool DownloadFile(string fileName, string savePath)
62         {
63             string strErrMsg = "";
64 
65             if (!CreateCommand(out strErrMsg))
66                 return false;70 
71             string sqlSelect = "select filename, filecontent from tb_flypath where filename=:FileName";
72             _Command.CommandText = sqlSelect;
73             _Command.CommandType = CommandType.Text;
74 
75             NpgsqlParameter paramFileName = _Command.CreateParameter();
76             paramFileName.NpgsqlDbType = NpgsqlTypes.NpgsqlDbType.Varchar;
77             paramFileName.ParameterName = "FileName";
78             paramFileName.Direction = ParameterDirection.Input;
79             paramFileName.Value = fileName;
80             _Command.Parameters.Add(paramFileName);
81 
82             _Connection.Open();
83             NpgsqlDataReader dr = _Command.ExecuteReader();
84             dr.Read();
85             byte[] buffer = (byte[])dr["filecontent"];
86             dr.Close();
87             _Connection.Close();
88 
89             //把文件保存到指定路徑 
90             File.WriteAllBytes(savePath, buffer);
91 
92             return true;
93         }

 

  Sqlite

  我們在講下 Sqlite 數據庫的操作方式,其實方法都一樣,沒什么太大區別,只是各個數據庫的存儲數據類型不太一樣。

  Sqlite 提供了 BLOB 類型進行存儲字節數據,所以創建表。

1 CREATE TABLE tb_flyPath
2 (
3     ID INTEGER primary key autoincrement , 
4     FileName VARCHAR not null ,
5     FileContent BLOB not null ,
6     CreateTime timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
7 )

  那么存取文件的方法大致無區別,PostgresSql 用的是 bytea 類型,那么 Sqlite 這里需要設置為 DbType.Binary 類型。

 1         /// <summary>
 2         /// 文件存儲入表
 3         /// </summary>
 4         /// <param name="filePath">文件路徑</param>
 5         /// <param name="id">節點ID</param>
 6         /// <returns></returns>
 7         public bool FileInsert(string filePath, string id)
 8         {
 9             string strErrMsg = "";
10             //讀取文件 
11             FileStream fs = File.OpenRead(filePath);
12             byte[] buffer = new byte[fs.Length];
13             fs.Read(buffer, 0, buffer.Length);
14 
15             if (!CreateCommand(out strErrMsg))
16                 return false;
17 
31             SQLiteParameter paramFileContent = _Command.CreateParameter();
32             paramFileContent.DbType = DbType.Binary;
33             paramFileContent.ParameterName = "FileContent";
34             paramFileContent.Direction = ParameterDirection.Input;
35             paramFileContent.Value = buffer;
36             _Command.Parameters.Add(paramFileContent);
37 
38             SQLiteParameter paramFileName = _Command.CreateParameter();
39             paramFileName.DbType = DbType.String;
40             paramFileName.ParameterName = "FileName";
41             paramFileName.Direction = ParameterDirection.Input;
42             paramFileName.Value = id;
43             _Command.Parameters.Add(paramFileName);
44 
45             string sqlInsert = "INSERT INTO tb_flyPath (filename,filecontent) VALUES (:FileName, :FileContent)";
46             _Command.CommandText = sqlInsert;
47             _Command.CommandType = CommandType.Text;
48 
49             _Connection.Open();
50             int result = _Command.ExecuteNonQuery();
51             _Connection.Close();
52 
53             return result > 0 ? true : false;
54         }
55 
56         /// <summary> 
57         /// 根據文件名從數據庫中獲取文件 
58         /// </summary> 
59         /// <param name="fileName">數據庫中的文件名</param> 
60         /// <param name="savePath">文件的保存路徑,包括文件名,如D:\test.fly</param> 
61         public bool DownloadFile(string fileName, string savePath)
62         {
63             string strErrMsg = "";
64 
65             if (!CreateCommand(out strErrMsg))
66                 return false;
67 
71             string sqlSelect = "select filename, filecontent from tb_flyPath where filename=:FileName";
72             _Command.CommandText = sqlSelect;
73             _Command.CommandType = CommandType.Text;
74 
75             SQLiteParameter paramFileName = _Command.CreateParameter();
76             paramFileName.DbType = DbType.String;
77             paramFileName.ParameterName = "FileName";
78             paramFileName.Direction = ParameterDirection.Input;
79             paramFileName.Value = fileName;
80             _Command.Parameters.Add(paramFileName);
81 
82             _Connection.Open();
83             SQLiteDataReader dr = _Command.ExecuteReader();
84             dr.Read();
85             byte[] buffer = (byte[])dr["filecontent"];
86             dr.Close();
87             _Connection.Close();
88 
89             //把文件保存到指定路徑 
90             File.WriteAllBytes(savePath, buffer);
91 
92             return true;
93         }

 

  如有講的不對,歡迎評論留言。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM