2017-07-05 50 views
0

我有代碼將包含文件名和二進制數據的對象列表從db傳遞到創建所有文件的循環。我的問題是下面的代碼執行並似乎創建文件正確(文件名&大小是預期的),但是,大多數文件打開時「損壞」。文件類型因圖像(jpg/png)到Word文檔,PowerPoint演示文稿和PDF文件而異。令人感到奇怪的是,PDF文件很好地工作,一切是「腐敗」從MemoryStream創建的某些文件損壞

我的代碼如下(attachment是,已經在這個階段創建的路徑中循環的對象)

if(Directory.Exists(attachmentPath)) 
{ 
    string absolutePath = attachmentPath + "\\importfiles\\" + parentfolders + "\\"; 

    // no need to check if it exists as it will ignore if it does 
    Directory.CreateDirectory(absolutePath); 
    absolutePath += filename; 
    try 
    { 
     byte[] byteStream = null; 
     object objSave = null; 

     objSave = attachment.Image; 
     BinaryFormatter tmpBinF = new BinaryFormatter(); 
     MemoryStream tmpMemStrm = new MemoryStream(); 
     tmpBinF.Serialize(tmpMemStrm, objSave); 
     byteStream = tmpMemStrm.ToArray(); 

     // Delete the file if it exists. 
     if (File.Exists(absolutePath)) 
     { 
      File.Delete(absolutePath); 
     } 

     // Create the file. 
     using (FileStream fs = File.Create(absolutePath)) 
     { 
      fs.Write(byteStream, 0, byteStream.Length); 
      fs.Dispose(); 
     } 

    } 

    catch (Exception ex) 
    { 
     Exceptions.Text += ex.ToString(); 
    } 
} 

我已經使用了來自MSDN的提示,並遵循this教程,但無法弄清楚爲什麼會發生這種情況。

非常感謝Amy用我的方法指出了這個問題,如果有人需要它,這裏是我的更新代碼,考慮她的回答。我還擴展了它以在數據庫中的表中添加日誌記錄供以後使用。

if (Directory.Exists(attachmentPath)) 
{ 
    // build path from the parts 
    string absolutePath = attachmentPath + "\\importfiles\\" + parentfolders + "\\"; 

    // no need to check if it exists as it will ignore if it does 
    Directory.CreateDirectory(absolutePath); 
    absolutePath += filename; 
    byte[] file = attachment.Image; 
    try 
    { 
     // Delete the file if it exists. 
     if (File.Exists(absolutePath)) 
     { 
      File.Delete(absolutePath); 
     } 

     // Create the file. 
     using (FileStream fs = File.Create(absolutePath)) 
     { 
      fs.Write(file, 0, file.Length); 
     } 

     // start logging to the database 

     // add the Stored procedure 
     string SP = "sp_add_attachment"; 

     // create the connection & command objects 
     MySqlConnection myConnection1 = new MySqlConnection(WPConnectionString); 
     MySqlCommand cmd1; 
     try 
     { 
      // open the connection 
      myConnection1.Open(); 

      cmd1 = myConnection1.CreateCommand(); 

      // assign the stored procedure string to the command 
      cmd1.CommandText = SP; 

      // define the command type 
      cmd1.CommandType = CommandType.StoredProcedure; 

      // pass the parameters to the Store Procedure 
      cmd1.Parameters.AddWithValue("@AttachmentID", attachment.ID); 
      cmd1.Parameters["@AttachmentID"].Direction = ParameterDirection.Input; 

      cmd1.Parameters.AddWithValue("@subpath", parentfolders); 
      cmd1.Parameters["@subpath"].Direction = ParameterDirection.Input; 

      cmd1.Parameters.AddWithValue("@filename", filename); 
      cmd1.Parameters["@filename"].Direction = ParameterDirection.Input; 

      // execute the command 
      int output = cmd1.ExecuteNonQuery(); 

      // close the connection 
      myConnection1.Close(); 
     } 
     catch (Exception ex) 
     { 
      Exceptions.Text += "MySQL Exception when logging:" + ex.ToString(); 
     } 

    } 

    catch (Exception ex) 
    { 
     Exceptions.Text += ex.ToString(); 
    } 
} 
+0

你可能不需要最後的'fs.Dispose()',因爲'using'的用法暗示了它。我懷疑這是問題的原因。 –

+0

Thanks @HoriaComan - 我會刪除它,因爲它不是必需的,當你指出它時很明顯! :) – Daniel

+0

你試圖寫的對象是'attachment.Image'否?它的格式是什麼?你怎麼知道這是一個合適的jpg/png開始,而不僅僅是像素矩陣,例如? –

回答

3

我不使用BinaryFormatter的認爲是適當的。如果attachment.Image是一個字節數組,只需將它寫入文件流即可。完全忘記內存流和二進制格式化程序。

Binary Formatter類用於將.Net類序列化爲字節數組。你已經有了一個字節數組,所以這一步不是必須的,而且是你的問題的根源。只有使用相同的二進制格式化程序才能在數據庫中創建Blob時,才能使用二進制格式化程序。但是你正在存儲文件,而不是.Net對象,所以在這裏沒有用。

我不知道爲什麼PDFs會加載時,其他文件不會。您必須使用十六進制編輯器檢查文件以查看更改的內容。

+0

是的,PDF文件的工作是這個問題最古怪的方面,但你的答案是完美的。謝謝 – Daniel

+0

可能產生的字節流只是四個字節的長度,然後是序列化PDF文檔的數組內容。可能是因爲PDF閱讀器在輸入處理方面非常鬆懈,並且他們知道在查找PDF文檔之前跳過一些腳本。 –