我使用FILESTREAM将文件保存到SQL Server 2008(Express)数据库,我遇到的麻烦是某些文件似乎在此过程中被破坏。
例如,如果我以一种较新的格式(docx或xslx)保存单词或excel文档,那么当我尝试打开文件时,我收到一条错误消息,说明数据已损坏且我喜欢word / excel尝试恢复它,如果我点击是办公室能够'恢复'数据并以兼容模式打开文件。
但是,如果我首先压缩文件然后解压缩内容后我可以毫无问题地打开文件。奇怪的是如果我将mp3文件保存到数据库然后我有相反的问题,我可以打开文件没问题,但如果我保存了MP3的压缩版本我甚至无法提取该zip文件的内容。当我试图保存pdf或power-point文件时,我遇到了类似的问题(pdf我只能读取,如果我先将其压缩,而ppt我根本无法阅读。)
更新:这是我用来写入数据库并阅读
的代码写入数据库:
SQL = "SELECT Attachment.PathName(), GET_FILESTREAM_TRANSACTION_CONTEXT() FROM Activity " +
"WHERE RowID = CAST(@RowID as uniqueidentifier)";
transaction = connection.BeginTransaction();
command.Transaction = transaction;
command.CommandText = SQL;
command.Parameters.Clear();
command.Parameters.Add(rowIDParam);
SqlDataReader readerFS = null;
readerFS= command.ExecuteReader();
string path = (string)readerFS[0].ToString();
byte[] context = (byte[])readerFS[1];
int length = context.Length;
SqlFileStream targetStream = new SqlFileStream(path, context, FileAccess.Write);
int blockSize = 1024 * 512; //half a megabyte
byte[] buffer = new byte[blockSize];
int bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
while (bytesRead > 0)
{
targetStream.Write(buffer, 0, bytesRead);
bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
}
targetStream.Close();
sourceStream.Close();
readerFS.Close();
transaction.Commit();
并阅读:
SqlConnection connection = null;
SqlTransaction transaction = null;
try
{
connection = getConnection();
connection.Open();
transaction = connection.BeginTransaction();
SQL = "SELECT Attachment.PathName(), + GET_FILESTREAM_TRANSACTION_CONTEXT() FROM Activity"
+ " WHERE ActivityID = @ActivityID";
SqlCommand command = new SqlCommand(SQL, connection);
command.Transaction = transaction;
command.Parameters.Add(new SqlParameter("ActivityID", activity.ActivityID));
SqlDataReader reader = command.ExecuteReader();
string path = (string)reader[0];
byte[] context = (byte[])reader[1];
int length = context.Length;
reader.Close();
SqlFileStream sourceStream = new SqlFileStream(path, context, FileAccess.Read);
int blockSize = 1024 * 512; //half a megabyte
byte[] buffer = new byte[blockSize];
List<byte> attachmentBytes = new List<byte>();
int bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
while (bytesRead > 0)
{
bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
foreach (byte b in buffer)
{
attachmentBytes.Add(b);
}
}
FileStream outputStream = File.Create(outputPath);
foreach (byte b in attachmentBytes)
{
byte[] barr = new byte[1];
barr[0] = b;
outputStream.Write(barr, 0, 1);
}
outputStream.Close();
sourceStream.Close();
command.Transaction.Commit();
答案 0 :(得分:5)
您的阅读代码不正确:
while (bytesRead > 0)
{
bytesRead = sourceStream.Read(buffer, 0, buffer.Length);
foreach (byte b in buffer)
{
attachmentBytes.Add(b);
}
}
如果bytesRead小于buffer.Length,您仍然将整个缓冲区添加到attachementBytes。因此,您总是通过在最后一个缓冲区postRead。
的末尾添加任何垃圾来破坏返回的文档除此之外,请允许我有一个真正的WTF时刻。读取流为List<byte>
??来吧!首先,我没有看到你需要读入中间内存存储的原因。您可以简单地通过缓冲区读取缓冲区并将每个缓冲区直接写入outputStream。其次,如果必须使用中间内存存储,请使用MemoryStream
,而不是List<byte>
。
答案 1 :(得分:1)