2010-04-05 42 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

相关问题