2011-01-12 36 views
2

使用Asp.Net MVC我創建了一個文件下載器。內置Asp.Net MVC功能的問題在於,它們不適用於非常大的文件下載,並且在某些瀏覽器中它們不會彈出「另存爲」對話框。所以我用自己的文章從msdn http://support.microsoft.com/kb/812406滾出。現在的問題是文件完全下載,但MD5校驗和不匹配,因爲服務器上的文件大小與下載文件大小不同(儘管1000次測試顯示下載執行得很好)。下面是代碼:創建自定義文件下載。 MD5散列不匹配

public class CustomFileResult : ActionResult 
{ 
    public string File { get; set; } 

    public CustomFileResult(string file) 
    { 
     this.File = file; 
    } 

    public override void ExecuteResult(ControllerContext context) 
    { 
     Stream iStream = null; 

     // Buffer to read 10K bytes in chunk: 
     byte[] buffer = new Byte[10000]; 

     // Length of the file: 
     int length; 

     // Total bytes to read: 
     long dataToRead; 

     // Identify the file name. 
     string filename = System.IO.Path.GetFileName(this.File); 

     try 
     { 
      // Open the file. 
      iStream = new System.IO.FileStream(this.File, System.IO.FileMode.Open, 
         System.IO.FileAccess.Read, System.IO.FileShare.Read); 


      // Total bytes to read: 
      dataToRead = iStream.Length; 

      context.HttpContext.Response.ContentType = "application/octet-stream"; 
      context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename); 

      // Read the bytes. 
      while (dataToRead > 0) 
      { 
       // Verify that the client is connected. 
       if (context.HttpContext.Response.IsClientConnected) 
       { 
        // Read the data in buffer. 
        length = iStream.Read(buffer, 0, 10000); 

        // Write the data to the current output stream. 
        context.HttpContext.Response.OutputStream.Write(buffer, 0, length); 

        // Flush the data to the HTML output. 
        context.HttpContext.Response.Flush(); 

        buffer = new Byte[10000]; 
        dataToRead = dataToRead - length; 
       } 
       else 
       { 
        //prevent infinite loop if user disconnects 
        dataToRead = -1; 
       } 
      } 
     } 
     catch (Exception ex) 
     { 
      // Trap the error, if any. 
      context.HttpContext.Response.Write("Error : " + ex.Message); 
     } 
     finally 
     { 
      if (iStream != null) 
      { 
       //Close the file. 
       iStream.Close(); 
      } 
      context.HttpContext.Response.Close(); 
     } 
    } 
} 

和執行:

return new CustomFileResult(file.FullName); 
+2

你不需要每次都重新初始化`buffer`。另外,使用`break;`。 – SLaks 2011-01-12 03:10:34

回答

1

原來,問題是缺少標題。

context.HttpContext.Response.AddHeader("Content-Length", iStream.Length.ToString()); 

添加該標題解決了問題。

-1

你的問題是在這裏:

length = iStream.Read(buffer, 0, 10000); 

// Write the data to the current output stream. 
context.HttpContext.Response.OutputStream.Write(buffer, 0, length); 

每一個循環,你會讀入的準確10,000字節的緩衝區,並編寫到流。這意味着有人下載的每個文件將以10,000的倍數爲單位。因此,如果我要從您的網站下載9,998字節的文件,我得到的文件將是10,000字節。這意味着散列永遠不會匹配。我的文件末尾會有2個空字節。

您需要添加一個檢查,以確保數據的量,讀的是> = 10K,並且如果不是,調整您的字節被留下的確切數額,並傳輸這一點。這應該可以解決哈希不匹配

嘗試這樣的事:

if (context.HttpContext.Response.IsClientConnected) 
{ 
// Read the data in buffer. 
if (dataToRead>=10000) 
{ 
    byte[] buffer = new byte[10000]; 
    length = 10000 
    context.HttpContext.Response.OutputStream.Write(buffer, 0, length); 
} 
else 
{ 
    byte[] buffer = new byte[dataToRead]; 
    length = buffer.Length; 
    context.HttpContext.Response.OutputStream.Write(buffer, 0, length); 
} 
// Flush the data to the HTML output. 
context.HttpContext.Response.Flush(); 

dataToRead = dataToRead - length; 
} 
+1

iStream.Read將返回它讀取的字節數。最後一次讀取將少於10,000次。 http://msdn.microsoft.com/en-us/library/system.io.filestream.read.aspx – 2011-01-12 03:17:24

0

一旦開始寫的OutputStream,儘量沖洗OutputStream的本身,而不是刷新響應: context.HttpContext.Response.OutputStream.Flush()