从C#读取/写入SQLServer2005/2008时,文件损坏?
我编写了两个小方法来将.docx(以及其他类型的文件)文件保存并加载到数据库中(Server2005/2008,以VarBinary(MAX)作为列)。一切似乎都很好,但当我读回文件时,它被创建了,但Word抱怨它被破坏了,但最后打开了它,里面有所有的东西。代码怎么了从C#读取/写入SQLServer2005/2008时,文件损坏?,c#,sql-server-2005,sql-server-2008,upload,download,C#,Sql Server 2005,Sql Server 2008,Upload,Download,我编写了两个小方法来将.docx(以及其他类型的文件)文件保存并加载到数据库中(Server2005/2008,以VarBinary(MAX)作为列)。一切似乎都很好,但当我读回文件时,它被创建了,但Word抱怨它被破坏了,但最后打开了它,里面有所有的东西。代码怎么了 public static void databaseFileRead(string varID, string varPathToNewLocation) { const int bufferSize =
public static void databaseFileRead(string varID, string varPathToNewLocation) {
const int bufferSize = 100;
byte[] outByte = new byte[bufferSize];
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP))
using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) {
sqlQuery.Parameters.AddWithValue("@varID", varID);
using (var sqlQueryResult = sqlQuery.ExecuteReader(CommandBehavior.Default))
while (sqlQueryResult != null && sqlQueryResult.Read()) {
using (FileStream stream = new FileStream(varPathToNewLocation, FileMode.OpenOrCreate, FileAccess.Write)) {
using (BinaryWriter writer = new BinaryWriter(stream)) {
long startIndex = 0;
long retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
while (retval == bufferSize) {
writer.Write(outByte);
writer.Flush();
startIndex += bufferSize;
retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
}
writer.Write(outByte, 0, (int) retval - 1);
writer.Flush();
writer.Close();
}
stream.Close();
}
}
}
}
public static void databaseFilePut(string varFilePath) {
FileStream stream = new FileStream(varFilePath, FileMode.Open, FileAccess.Read);
BinaryReader reader = new BinaryReader(stream);
byte[] file = reader.ReadBytes((int) stream.Length);
reader.Close();
stream.Close();
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP))
using (var sqlWrite = new SqlCommand("INSERT INTO Raporty (RaportPlik) Values(@File)", varConnection)) {
sqlWrite.Parameters.Add("@File", SqlDbType.Binary, file.Length).Value = file;
sqlWrite.ExecuteNonQuery();
}
}
编辑:
我已经根据建议更改了代码,将bufferSize设置为4096,但仍然不可行
原始文件的大小为48,0 KB(字节:49 225),磁盘大小为52,0 KB(字节:53 248)(Win 7属性显示了这一点)。而从数据库中取出的文件大小为52,0 KB(字节:53 248),磁盘上的文件大小为52,0 KB(字节:53 248)
这一切都发生在Win 7 x64开发机器上,我卸载了Eset Smart Security以确保安全
编辑2:
因此,我添加了另一种“方法”来实现这一点,它似乎做到了这一点。唯一值得注意的区别是没有使用BinaryWriter和Byte[]blob有点奇怪的定义。
很奇怪,不是吗
public static void databaseFileRead(string varID, string varPathToNewLocation) {
const int bufferSize = 4096;
byte[] outByte = new byte[bufferSize];
using (var varConnection = Locale.sqlConnectOneTime(Locale.sqlDataConnectionDetailsDZP))
using (var sqlQuery = new SqlCommand(@"SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = @varID", varConnection)) {
sqlQuery.Parameters.AddWithValue("@varID", varID);
using (var sqlQueryResult = sqlQuery.ExecuteReader())
while (sqlQueryResult != null && sqlQueryResult.Read()) {
using (FileStream stream = new FileStream(varPathToNewLocation, FileMode.OpenOrCreate, FileAccess.Write))
using (BinaryWriter writer = new BinaryWriter(stream)) {
long startIndex = 0;
long retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
while (retval > 0) {
writer.Write(outByte);
writer.Flush();
startIndex += retval;
retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
}
}
}
}
Byte[] blob = null;
FileStream fs = null;
const string sConn = Locale.sqlDataConnectionDetailsDZP;
SqlConnection conn = new SqlConnection(sConn);
SqlCommand cmd = new SqlCommand("SELECT [RaportPlik] FROM [dbo].[Raporty] WHERE [RaportID] = " + varID, conn);
conn.Open();
SqlDataReader sdr = cmd.ExecuteReader();
sdr.Read();
blob = new Byte[(sdr.GetBytes(0, 0, null, 0, int.MaxValue))];
sdr.GetBytes(0, 0, blob, 0, blob.Length);
sdr.Close();
conn.Close();
fs = new FileStream("c:\\Builder.docx", FileMode.Create, FileAccess.Write);
fs.Write(blob, 0, blob.Length);
fs.Close();
}
代码可能没有问题。我会看看你在那台服务器上有什么病毒扫描软件,然后马上卸载它。我看到Norton和McAfee都是clobber文件,没有任何迹象表明他们更改了任何内容。代码可能没有问题。我会看看你在那台服务器上有什么病毒扫描软件,然后马上卸载它。我看到Norton和McAfee都是clobber文件,没有任何迹象表明他们改变了什么。您的
数据库文件读取方法中有一个错误
考虑一下:您的缓冲区大小为100字节(非常小-我建议最小值为4096字节!),您的循环如下所示:
while (retval == bufferSize)
{
writer.Write(outByte);
writer.Flush();
startIndex += bufferSize;
retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
}
好的,这很好,直到您的文件中只剩下73个字节需要处理——在这种情况下,最后一次调用
retval=sqlQueryResult.GetBytes(0,startIndex,outByte,0,bufferSize)
将在retval
中返回“73”,由于这是而不是==bufferSize
,因此将中止。因此,您总是跳过最后两个字节
您需要做的是:
while (retval > 0)
{
writer.Write(outByte);
writer.Flush();
startIndex += retval;
retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
}
这样,在读取最后73个字节时,您将得到retval=73
,并写出最后73个字节,然后对sqlQueryResult的下一次调用应返回retval=0
,然后终止循环
试试看——我很确定这就是这个错误的原因
Marc您的数据库文件读取方法中有一个错误
考虑一下:您的缓冲区大小为100字节(非常小-我建议最小值为4096字节!),您的循环如下所示:
while (retval == bufferSize)
{
writer.Write(outByte);
writer.Flush();
startIndex += bufferSize;
retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
}
好的,这很好,直到您的文件中只剩下73个字节需要处理——在这种情况下,最后一次调用
retval=sqlQueryResult.GetBytes(0,startIndex,outByte,0,bufferSize)
将在retval
中返回“73”,由于这是而不是==bufferSize
,因此将中止。因此,您总是跳过最后两个字节
您需要做的是:
while (retval > 0)
{
writer.Write(outByte);
writer.Flush();
startIndex += retval;
retval = sqlQueryResult.GetBytes(0, startIndex, outByte, 0, bufferSize);
}
这样,在读取最后73个字节时,您将得到retval=73
,并写出最后73个字节,然后对sqlQueryResult的下一次调用应返回retval=0
,然后终止循环
试试看——我很确定这就是这个错误的原因
Marc以下代码似乎工作正常,没有错误。跳过使用BinaryWriter
可以正确地写入文件。为什么使用BinaryWriter
会破坏我不知道的文件:-)
下面的代码似乎可以正常工作。跳过使用BinaryWriter
可以正确地写入文件。为什么使用BinaryWriter
会破坏我不知道的文件:-)
服务器上没有防病毒/防火墙。服务器上没有防病毒/防火墙。我已将代码替换为您的代码,但仍然会出错。我也把buffersize改成了4096。我还认为writer.Write(outByte,0,(int)retval-1)
正在处理丢失的73个字节。代码基于@madboy:相同的错误?你有其他信息吗?磁盘上生成的文件大小是100 resp的精确倍数。4096字节???@madboy:是的,没错-我忽略了最后一个编写器。编写语句。是的,这将处理最后剩余的字节…我现在做了另一个测试。原始文件显示:48,0 KB(bajtów:49 225)为大小,52,0 KB(bajtów:53 248)为磁盘大小(Win 7属性显示了这一点)。而从数据库中取出的文件大小为52,0 KB(bajtów:53 248),磁盘大小为52,0 KB(bajtów:53 248)。请记住,我赢了7 x64,可能是什么原因使它变糟了?我已经用工作代码更新了main poste(read函数的第二部分)。似乎使用BinaryWriter并不是最好的选择。不知道你为什么:-)我已经用你的代码替换了代码,但仍然出错。我也把buffersize改成了4096。我还认为writer.Write(outByte,0,(int)retval-1)
正在处理丢失的73个字节。代码基于@madboy:相同的错误?你有其他信息吗?磁盘上生成的文件大小是100 resp的精确倍数。4096字节???@madboy:是的,没错-我忽略了最后一个编写器。编写语句。是的,这将处理最后剩余的字节…我现在做了另一个测试。原始文件显示:48,0 KB(bajtów:49 225)为大小,52,0 KB(bajtów:53 248)为磁盘大小(Win 7属性显示了这一点)。而从数据库中取出的文件大小为52,0 KB(bajtów:53 248),磁盘大小为52,0 KB(bajtów:53 248)。请记住,我赢了7 x64,可能是什么原因使它变糟了?我已经用工作代码更新了main poste(read函数的第二部分)。似乎使用BinaryWriter并不是最好的选择。不知道你为什么:-)