Я написал два небольших метода для сохранения и загрузки файлов .docx (и позже для других типов файлов) в базу данных (SERVER 2005/2008 с VarBinary (MAX) в качестве столбца). Все кажется хорошим, но когда я читаю файл обратно, он создается, но Word жалуется, что он поврежден, но, наконец, открывает его со всем в нем. Что не так с кодом?
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();
}
}
Редактировать:
Я изменил код в соответствии с предложением иметь размер буфера 4096, но он все еще не работает.
Оригинальный файл сообщает: 48,0 КБ (байт: 49 225) как размер и 52,0 КБ (байт: 53 248) как размер на диске (свойства Win 7 показывают это). Размер файла, извлеченного из базы данных, составляет 52,0 КБ (байт: 53 248), а размер диска 52,0 КБ (байт: 53 248).
Все это происходит на компьютере разработчика с Win 7 x64, я просто удалил Eset Smart Security, чтобы быть уверенным.
Edit2:
Итак, я добавил еще один «способ» сделать это с веб-страницы , и это, похоже, помогает. Единственным заметным отличием является отсутствие использования BinaryWriter и немного странное определение для объекта Blob Byte [].
Странно, не правда ли?
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();
}