2011-07-25 22 views
3

ファイル名が列であるGridViewを持つWebフォームがあります。 filenameをクリックすると、Open/Saveダイアログボックスがユーザに提示されます。ほとんどの場合、エラーメッセージ "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(filename)を使用していない理由はありますか? – Willem

+0

データベースのファイルのダウンロード履歴を保存する必要があります。ダウンロードボタンのクリックイベントを挿入するだけで、ユーザーがダウンロードをキャンセルしても、行がテーブルに挿入されます。このような状況を避けるために、ファイルをパケットで送信するこのコードを実装しました。 – KhD

+0

「保存」画面がユーザーの入力を待っている間に、ほとんどのブラウザーがファイルをダウンロードするため、クライアントが文書を保存したことを確認できません。ユーザーがキャンセルすると、ブラウザーが既に完全なファイルをtempディレクトリにダウンロードしている可能性が高くなります。 – Willem

答えて

1

私はあなたが既にResponse.WriteFileを使うことができると思います。すでに作成したFileInfoオブジェクトを使うべきです。コード:あなたの代わりに「アプリケーション/オクテットストリーム」の、特定のContentTypeをを知っている場合

 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(); 
     } 

あなたは

+0

あなたの助けWillemに感謝します。私のコードからResponse.Flush()を削除すると問題が解決しました。 – KhD

2

The remote host closed the connection. The error code is 0x80072746.(例についてはhereを参照してください)ファイルのMIMEタイプにそれを変更することができます - この例外はありますサーバーが接続を終了する前にブラウザーがダウンロードを完了しなかった場合に発生します。

これは、あなたのResponse.BinaryWriteの後ろにファイルとsqlを書くあなたの奇妙なスキームが原因である可能性があります。

ダウンロード用のカスタムサーバーを作成する場合は、独自のクライアントブラウザを作成してコードについて知らなくても、接続が失われる可能性があります。
また、転送されたバイトについてのチェックは意味をなさない - クライアントに受け入れられたバイトについては、を知ることはできません。

ですので、Response.WriteFile(filename)を強くお勧めします。

+0

ありがとうございます。 私はResponse.WriteFile(filename)を使用していましたが、これを使用して、開始前にユーザーがダウンロードをキャンセルしたのか、ダウンロード中にキャンセルしたのかを知る方法がありません。ユーザーがファイルを正常にダウンロードした場合(または少なくともサーバーからファイル全体が送信された場合)、この情報をデータベースに書き込む必要があります。この機能を実装する方法があればお勧めします。私はそれをgoogledし、これは私が見つけることができる最善の方法だった。 この例外に関しては、これはWriteFile()メソッドでも発生していました。 – KhD