2011-07-25 97 views
3

我有一個GridView,它的文件名是列。如果您單擊文件名,則向用戶呈現打開/保存對話框。大多數情況下,這會引發異常,並顯示錯誤消息 - The remote host closed the connection. The error code is 0x80072746下載文件會引發異常

此錯誤對除Firefox以外的任何其他瀏覽器中的用戶不可見。在Firefox中,所選文件會在頁面本身上呈現,並且在某段時間後,頁面會發出錯誤 - 連接已重置。

我正在下載文件,將其分解爲數據包,因爲我必須確定文件是否已完全下載,然後將此條目寫入數據庫表。

我已將Buffer="false"放在頁面指令中,但它不起作用。 我嘗試從我的代碼中刪除Response.Flush(),但無濟於事。

我的文件下載的代碼如下:

LinkButton btnTemp = (LinkButton)sender; 
GridViewRow row = (GridViewRow)btnTemp.NamingContainer; 
HiddenFieldFullFileName.Value = row.Cells[1].Text; 

FileInfo file = new FileInfo(HiddenFieldFullFileName.Value); 
if (file.Exists) 
{ 
    string filePath="", fileName=""; 

    //store filepath and filename in separate variables 
    string[] temp = row.Cells[1].Text.Split('\\'); 
    for (int j = 0; j < temp.Length; j++) 
    { 
     if (j < (temp.Length - 1)) 
      if(j==0) 
       filePath = filePath + temp[j]; 
      else 
       filePath = filePath + "\\" + temp[j]; 
     else 
      fileName = temp[j]; 

    } 
    FileStream myFile = new FileStream(row.Cells[1].Text, FileMode.Open,FileAccess.Read, FileShare.ReadWrite); 

    //Reads file as binary values 
    BinaryReader _BinaryReader = new BinaryReader(myFile); 

    long startBytes = 0; 
    string lastUpdateTimeStamp = File.GetLastWriteTimeUtc(filePath).ToString("r"); 
    string _EncodedData = HttpUtility.UrlEncode(fileName, Encoding.UTF8) + lastUpdateTimeStamp; 

    //Clear the content of the response 
    Response.Clear(); 
    Response.Buffer = false; 
    Response.AddHeader("Accept-Ranges", "bytes"); 
    Response.AppendHeader("ETag", "\"" + _EncodedData + "\""); 
    Response.AppendHeader("Last-Modified", lastUpdateTimeStamp); 

    //Set the ContentType 
    Response.ContentType = "application/octet-stream"; 

    //Add the file name and attachment, 
    //which will force the open/cancel/save dialog to show, to the header 
    Response.AddHeader("Content-Disposition", "attachment;filename=" + file.Name); 

    //Add the file size into the response header 
    Response.AddHeader("Content-Length", (file.Length - startBytes).ToString()); 
    Response.AddHeader("Connection", "Keep-Alive"); 

    //Set the Content Encoding type 
    Response.ContentEncoding = Encoding.UTF8; 

    //Send data 
    _BinaryReader.BaseStream.Seek(startBytes, SeekOrigin.Begin); 

    //Dividing the data in 1024 bytes package 
    int maxCount = (int)Math.Ceiling((file.Length - startBytes + 0.0)/1024); 

    //Download in block of 1024 bytes 
    int i; 
    for (i = 0; i < maxCount && Response.IsClientConnected; i++) 
    { 
     Response.BinaryWrite(_BinaryReader.ReadBytes(1024)); 
     Response.Flush(); 
    } 

    //compare packets transferred with total number of packets 
    if (i >= maxCount) 
    { 
     //get the IP address of user 
     string ipAddress = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"]; 
     if (ipAddress == null) 
     { 
      ipAddress = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; 
     } 

     //write the download information to database table 

    } 


    //Close Binary reader and File stream 
    _BinaryReader.Close(); 
    myFile.Close(); 
} 

什麼是問題的根源?

+2

有沒有原因你沒有使用一個簡單的Response.WriteFile(文件名)? – Willem

+0

我必須在數據庫中存儲文件的下載歷史記錄。如果我只是在下載按鈕單擊事件上執行插入操作,則即使用戶取消下載,表格中也會插入一行。爲了避免這種情況,我已經實現了這個代碼,其中文件以數據包的形式發送。 – KhD

+0

即使你不能確定客戶端保存了文檔,因爲大多數瀏覽器在「另存爲」屏幕等待用戶輸入時下載文件。如果用戶取消,瀏覽器很有可能已經將整個文件下載到臨時目錄。 – Willem

回答

1

我想你可以使用Response.WriteFile,並且你應該使用你已經創建的FileInfo對象。代碼:

 LinkButton btnTemp = (LinkButton)sender; 
     GridViewRow row = (GridViewRow)btnTemp.NamingContainer; 
     HiddenFieldFullFileName.Value = row.Cells[1].Text; 

     FileInfo file = new FileInfo(HiddenFieldFullFileName.Value); 
     if (file.Exists) 
     { 

      string lastUpdateTimeStamp = file.LastWriteTimeUtc.ToString("r"); 
      string _EncodedData = HttpUtility.UrlEncode(file.Name, Encoding.UTF8) + lastUpdateTimeStamp; 

      //Clear the content of the response 
      Response.Clear(); 
      Response.AppendHeader("ETag", "\"" + _EncodedData + "\""); 
      Response.AppendHeader("Last-Modified", lastUpdateTimeStamp); 

      //Set the ContentType 
      Response.ContentType = "application/octet-stream"; 

      //Add the file name and attachment, 
      //which will force the open/cancel/save dialog to show, to the header 
      Response.AddHeader("Content-Disposition", "attachment;filename=" + file.Name); 

      //Send data 
      Response.WriteFile(file.FullName); 
      Response.End(); 
     } 

如果您知道具體的contentType然後,而不是「應用程序/八位字節流」你可以改變你的文件的MIME類型(見here的例子)

+0

感謝您的幫助Willem。從我的代碼中刪除Response.Flush()解決了這個問題。 – KhD

2

The remote host closed the connection. The error code is 0x80072746. - 此異常如果瀏覽器在您的服務器結束連接之前未完成下載,則會提出。

這可能是因爲你的文件和sql後奇怪的方案Response.BinaryWrite

如果您想創建一些自定義服務器進行下載,您還應該創建自定義客戶端 - 瀏覽器不知道任何關於您的代碼的信息,並且他可能會失去他的連接。
此外,您檢查傳輸的字節是沒有意義的 - 您無法知道客戶端接受的字節

所以我強烈推薦Response.WriteFile(filename)

+0

感謝您的回覆。 早些時候,我已經使用Response.WriteFile(文件名),但使用此我無法知道,如果用戶取消下載甚至開始之前,或在下載中取消。如果用戶成功下載文件(或者至少從服務器發送完整文件),那麼我必須將這些信息寫入數據庫。如果你有更好的實現這個功能的方法,請建議。我搜索了它,這是我能找到的最好的方式。 就這個異常而言,即使使用WriteFile()方法也會發生這種情況。 – KhD