2013-07-11 89 views
0

我試圖保存在我的D:目錄中的圖像,並完成此操作,我保存在Session我的FileUpload組件的一些信息。文件通過流保存,但無法打開

在我的方法稱爲btnConfirm_Click創建我Session,在我btnSave_Click方法我恢復此信息並嘗試保存文件,但是當我在D:目錄查詢,該文件存在,但是當我打開這個文件,我看到了該消息:The windows photo viewer can not open this picture because the file appears to be damaged, corrupted, or is too big ..

有人可以幫助我嗎?

C#代碼

protected void btnConfirm_Click(object sender, EventArgs e) 
{ 
if (FileUpload1.HasFile) 
      { 
       string sFileName = FileUpload1.FileName; 
       string fileExtension = System.IO.Path.GetExtension(sFileName).ToLower(); 
       foreach (string ext in new string[] { ".jpeg", ".jpg", ".png" }) 
       { 
        if (fileExtension == ext) 
        { 
         Session["Document"] = sFileName + fileExtension; 
         Session["Byte"] = FileUpload1.FileBytes; 
         Session["Content"] = FileUpload1.FileContent; 
         byte[] b = (byte[])Session["Byte"]; 
        } 
       } 
      } 
} 


protected void btnSave_Click(object sender, EventArgs e) 
     { 
       if (Session["Document"].ToString() != null) 
       { 
        try 
        { 
         byte[] byteArray = Encoding.UTF8.GetBytes(Session["Content"].ToString());       
         MemoryStream stream = new MemoryStream(byteArray); 

         sPath = "D:/123.jpg"; 
         FileStream fileStream = File.Create(sPath, (int)stream.Length);       
         byte[] bytesInStream = new byte[stream.Length]; 
         stream.Read(bytesInStream, 0, bytesInStream.Length);       
         fileStream.Write(bytesInStream, 0, bytesInStream.Length); 
        } 
        catch 
        { 
        } 
       } 
     } 

回答

5
byte[] byteArray = Encoding.UTF8.GetBytes(Session["Content"].ToString()); 

這條線看起來很不對。您正在使用一個字符串(編碼爲UTF8)並嘗試將其轉換爲二進制JPG圖像。這不起作用。您需要將原始圖像保存爲二進制(不是文本+編碼)形式。當您將byte[]轉換爲string(反之亦然)時,會有信息丟失,因爲文本編碼不能(通常)代表所有字節序列。

由於@PanagiotisKanovas提到,您希望獲得Session['Content']數據流。另外,您不關閉流,所以當您嘗試打開文件時,對象仍可能被鎖定。

using (FileStream fileStream = File.Create(sPath, (int)stream.Length)) { 
    byte[] bytesInStream = new byte[stream.Length]; 
    stream.Read(bytesInStream, 0, bytesInStream.Length);       
    fileStream.Write(bytesInStream, 0, bytesInStream.Length); 
} 
+2

和會話[「內容」]是一個流,而不是字節數組 –

+0

@JeffFoster謝謝!有用。 –

0

嘗試包裹FileStream在using語句。

的FileStream裁判: http://msdn.microsoft.com/en-us/library/system.io.filestream.aspx

這是一般參考流: http://msdn.microsoft.com/en-us/library/system.io.stream.aspx

爲什麼你在using語句來包裝這個說法? 當您在代碼中使用託管資源(如文件,數據庫連接或此類任何其他資源)時,必須手動指定何時將這些資源從託管堆(RAM)中釋放。那麼,這不是100%有效的語句,因爲當垃圾收集啓動並移除所有未使用的對象時,這可能會自動發生。有幾點你必須知道,以瞭解你應該寫什麼樣的代碼。

1)垃圾回收僅在內存壓力上啓動,而不是定時器。
2)每個託管資源都通過繼承SafeHandle類來實現。 http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx這個抽象類有一個名爲Dispose()的方法,它只能安全​​地釋放它創建的任何託管資源。垃圾收集器或手動調用時會調用dispose方法。例如,使用建設是一個捷徑,下面的代碼:

var file; 
try{ // code } 
finally { file.Dispose(); } 

PS:大多數時候,你應該避免using聲明,還要求Dispose()。爲什麼?因爲你有GC,讓它做他的工作。如果你有問題,這意味着你必須仔細看看你的代碼。讓GC做它最擅長的事情。最後,僅在您確定沒有其他人使用您的託管資源(例如在另一個線程中)時才使用usingDispose()

+0

*爲什麼?(實際上我知道答案,但OP可能不理解,甚至不知道'IDisposable'模式) –

+0

這就是爲什麼我將他重定向到MSDN上的FileStream頁面。 – mynkow

+0

沒有什麼有用的理解在這個頁面的一次性模式。只有所需的方法(Dispose)存在。 Stream實現IDisposable的事實甚至沒有被指定。 –

1

該消息表示文件不包含圖像數據。您的代碼永遠不會將文件的內容存儲到磁盤。

它所做的是獲取流(FileUpload.FileContent)對象(通常爲類型的名稱)的字符串表示形式將此名稱轉換爲Unicode字符串,然後嘗試將其轉換爲二進制形式作爲UFT8字符串,最後將結果存儲在文件中。

Session["Content"]的內容是原始流,因此您可以使用Stream.CopyTo將一個流的內容複製到另一個流,例如。

var sourceStream=(Stream)Session["Content"]; 
using(var fileStream=File.Create(targetPath,sourceStream.Length); 
{ 
    sourceStream.CopyTo(fileStream); 
} 

更好的是,根本不要使用Session。除非有導致FileUpload1控制失去它的內容,當你執行你的btnSave_Click處理其內容將仍然可用。在這種情況下,您可以使用FileUpload.Save將文件直接保存到磁盤。

此外,使用Session是放錯了地方來存儲文件數據。會話使用機器的內存或數據庫來存儲其數據,這可能會導致在您存儲大量數據時性能較差。會議時間長,這意味着該文件的數據將保留在內存中即使你不再需要它,除非你明確地將其刪除活路。

+0

謝謝!有用。 –

相關問題