2010-04-05 40 views

回答

102

由於沒有提到你是什麼數據庫,我假設SQL Server。以下解決方案適用於2005年和2008年

你必須創建表VARBINARY(MAX)爲一列。在我的示例中,我創建了表Raporty,列RaportPlikVARBINARY(MAX)列。

方法把file到數據庫中drive

public static void databaseFilePut(string varFilePath) { 
    byte[] file; 
    using (var stream = new FileStream(varFilePath, FileMode.Open, FileAccess.Read)) { 
     using (var reader = new BinaryReader(stream)) { 
      file = reader.ReadBytes((int) stream.Length);  
     }   
    } 
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
    using (var sqlWrite = new SqlCommand("INSERT INTO Raporty (RaportPlik) Values(@File)", varConnection)) { 
     sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file; 
     sqlWrite.ExecuteNonQuery(); 
    } 
} 

此法是從數據庫中獲取file,並將其保存在drive

public static void databaseFileRead(string varID, string varPathToNewLocation) { 
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
    using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) { 
     sqlQuery.Parameters.AddWithValue("@varID", varID); 
     using (var sqlQueryResult = sqlQuery.ExecuteReader()) 
      if (sqlQueryResult != null) { 
       sqlQueryResult.Read(); 
       var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))]; 
       sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length); 
       using (var fs = new FileStream(varPathToNewLocation, FileMode.Create, FileAccess.Write)) 
        fs.Write(blob, 0, blob.Length); 
      } 
    } 
} 

這種方法是從數據庫中獲得file並將其作爲MemoryStream

public static MemoryStream databaseFileRead(string varID) { 
    MemoryStream memoryStream = new MemoryStream(); 
    using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
    using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) { 
     sqlQuery.Parameters.AddWithValue("@varID", varID); 
     using (var sqlQueryResult = sqlQuery.ExecuteReader()) 
      if (sqlQueryResult != null) { 
       sqlQueryResult.Read(); 
       var blob = new Byte[(sqlQueryResult.GetBytes(0, 0, null, 0, int.MaxValue))]; 
       sqlQueryResult.GetBytes(0, 0, blob, 0, blob.Length); 
       //using (var fs = new MemoryStream(memoryStream, FileMode.Create, FileAccess.Write)) { 
       memoryStream.Write(blob, 0, blob.Length); 
       //} 
      } 
    } 
    return memoryStream; 
} 

這種方法是把MemoryStream到數據庫:

public static int databaseFilePut(MemoryStream fileToPut) { 
     int varID = 0; 
     byte[] file = fileToPut.ToArray(); 
     const string preparedCommand = @" 
        INSERT INTO [dbo].[Raporty] 
           ([RaportPlik]) 
         VALUES 
           (@File) 
         SELECT [RaportID] FROM [dbo].[Raporty] 
      WHERE [RaportID] = SCOPE_IDENTITY() 
        "; 
     using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetails)) 
     using (var sqlWrite = new SqlCommand(preparedCommand, varConnection)) { 
      sqlWrite.Parameters.Add("@File", SqlDbType.VarBinary, file.Length).Value = file; 

      using (var sqlWriteQuery = sqlWrite.ExecuteReader()) 
       while (sqlWriteQuery != null && sqlWriteQuery.Read()) { 
        varID = sqlWriteQuery["RaportID"] is int ? (int) sqlWriteQuery["RaportID"] : 0; 
       } 
     } 
     return varID; 
    } 

快樂編碼:-)

1

您使用的數據庫是?通常你不將文件保存到數據庫中,但我認爲SQL 2008有支持它...

文件是二進制數據,因此UTF-8不要緊,這裏..

UTF當您嘗試8個事宜將字符串轉換爲字節數組......不是將文件轉換爲字節數組。

0

是,通常存儲在數據庫中的文件的最好方法是將字節數組保存在BLOB列。您可能需要多列來額外存儲文件的元數據,例如名稱,擴展名等。

它並不總是將文件存儲在數據庫中的一個好主意 - 例如,如果你在其中存儲文件的數據庫規模將快速增長。但這一切都取決於您的使用場景。

7

它確實取決於數據庫服務器。

例如,SQL Server 2008的支持FILESTREAM數據類型正是這種情況。

除此之外,如果你使用一個MemoryStream,它有一個ToArray()方法,將轉換爲byte[] - 這可以用於填充一個varbinary場..

9

雖然可以以這種方式存儲文件,它有顯著權衡:

  • 大多數的DB不是二進制數據的巨大數量的優化,和查詢性能通常會顯着下降作爲表漲大,即使有索引。 (具有FILESTREAM列類型的SQL Server 2008是規則的例外。)
  • 數據庫備份/複製變得非常慢。
  • 處理損壞的驅動器和200萬張圖像比更換損壞的數據庫表更容易 - 只需更換RAID上的磁盤。
  • 如果意外刪除文件系統上的十幾圖像,您的操作人可以從備份很容易地替換他們,而且由於表索引是微小比較起來,它可以快速恢復。如果您不小心刪除了大型數據庫表中的十幾張圖片,則需要等待很長時間才能從備份恢復數據庫,同時使整個系統癱瘓。

這些只是我能從頭頂上想出的一些缺點。對於小型項目,可能值得以這種方式存儲文件,但如果您正在設計企業級軟件,我強烈建議不要這樣做。

2

確認我能夠用張貼MadBoy和編輯答案由Otiel在MS SQL Server 2012和2014以及之前列出的使用varbinary(MAX)列的版本之外。

如果您想知道爲什麼您不能在SQL Server表設計器中將「Filestream」(在單獨的答案中註明)作爲數據類型,或者您爲什麼不能使用T-SQL將列的數據類型設置爲「Filestream」,那是因爲FILESTREAM是varbinary(MAX)數據類型的存儲屬性。它本身不是數據類型。

查看的數據庫上設置和啓用FILESTREAM這些文章: https://msdn.microsoft.com/en-us/library/cc645923(v=sql.120).aspx

http://www.kodyaz.com/t-sql/default-filestream-filegroup-is-not-available-in-database.aspx

配置完成後,一個FILESTREAM使VARBINARY(max)列可以被添加像這樣:

ALTER表表名

ADD ColumnName varbinary(max)FILESTREAM NULL

GO

相關問題