我已經寫了兩個小方法來保存和加載.docx(以及其他類型的文件)文件到數據庫(SERVER 2005/2008與VarBinary(MAX)列)。一切似乎都很好,但是當我讀取文件時,它創建了,但Word抱怨它已損壞,但最終將其中的所有內容都打開。代碼有什麼問題?從C#的SQLServer 2005/2008讀取/寫入文件時會損壞文件嗎?
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 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。
EDIT2:
所以我增加了一個「辦法」從webpage做到這一點,似乎這樣的伎倆。唯一明顯的區別是缺少使用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();
}
服務器上沒有防病毒/防火牆。 – MadBoy 2010-03-02 17:37:36