保存任何文件到数据库中,只是将其转换为字节数组?
将文件转换为字节数组是将任何文件格式保存到磁盘或数据库variables二进制列的最佳方式?
所以如果有人想要保存一个.gif或.doc / .docx或.pdf文件,我可以将它转换为一个byteray的UFT8并将其保存到数据库中作为一个字节stream?
由于它没有提到你是什么数据库,我假设SQL Server。 以下解决scheme适用于2005年和2008年。
您必须创build与VARBINARY(MAX)
作为其中一列的表。 在我的例子中,我创build了Table Raporty
其中列RaportPlik
是VARBINARY(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; }
快乐编码:-)
虽然您可以用这种方式存储文件,但它有很大的折衷:
- 大多数数据库没有针对大量的二进制数据进行优化,查询性能通常会随着表的膨胀而显着降低,即使有索引。 (具有FILESTREAM列types的SQL Server 2008是规则的例外。)
- 数据库备份/复制变得非常缓慢。
- 处理损坏的驱动器与200万张图像 – 更换RAID上的磁盘 – 比损坏的数据库表要容易得多。
- 如果您不小心删除了文件系统上的十几个映像,那么您的操作人员可以很容易地从备份中replace它们,并且由于表索引比较小,所以可以快速恢复。 如果您不小心删除了大型数据库表中的十几张图片,则需要等待很长时间才能从备份中恢复数据库,同时使整个系统瘫痪。
这些只是我能从头顶上拿出来的一些缺点。 对于小型项目来说,以这种方式存储文件可能是值得的,但如果你正在devise企业级软件,我强烈build议不要这样做。
这真的取决于数据库服务器。
例如,对于这种情况,SQL Server 2008支持FILESTREAM
数据types。
除此之外,如果您使用MemoryStream
,它有ToArray()
方法将转换为一个byte[]
– 这可以用于填充varbinary
字段..
确认我能够使用由MadBoy发布并由Otiel编辑的在MS SQL Server 2012和2014中的回答以及之前列出的使用varbinary(MAX)列的版本。
如果您想知道为什么您不能在SQL Server表devise器中将“Filestream”(在单独的答案中指出)作为数据types,或者您为什么不能使用T-SQL将列的数据types设置为“Filestream”,那是因为FILESTREAM是存储varbinary(MAX)数据types的属性。 它本身不是一个数据types。
请参阅以下关于在数据库上设置和启用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
configuration完成后,可以添加启用了文件stream的varbinary(max)列,如下所示:
ALTER TABLE TableName
ADD ColumnName varbinary(max)FILESTREAM NULL
走
你在用什么数据库? 通常你不把文件保存到数据库,但我认为SQL 2008支持它…
一个文件是二进制数据,因此UTF 8在这里并不重要..
当您尝试将string转换为字节数组时,UTF 8很重要…而不是将文件转换为字节数组。
是的,通常将文件存储在数据库中的最佳方式是将字节数组保存在BLOB列中。 您可能需要多列来额外存储文件的元数据,例如名称,扩展名等。
将文件存储在数据库中并不总是一个好主意 – 例如,如果在其中存储文件,数据库大小将会快速增长。 但是这一切都取决于你的使用场景。