2011-09-23 31 views
1

私は、ユーザーの進捗状況を保存するftpユーティリティのプロトタイプを作成しており、インターネットが切断された場合に開始した場所からファイルを再アップロードします。 (接続が遅いクライアント向けです)。FtpWebRequest.GetRequestStream()disconnect after after

アイデアは、ファイルストリームとftpストリームを開き、メモリのチャンクでftpストリームに書き込むことです。例外が発生した場合(すなわち、切断によるIOException)、ftpサーバに書き込まれたバイト数はログファイルに保存され、起動時に読み込まれます。

このコードは、トランザクションがキャンセルされた場合に素晴らしい作品が、クライアントが切断される場合には、その後のftpストリームがサーバ側でクリーンアップされることはありません - 私は受け取る...

リモートサーバーが返さエラー:(550)ファイルが使用できません(たとえば、ファイルが見つからず、アクセスできません)。

指定されたファイルのftpストリームを再要求するとき。コードは

 //Create FTP Web Request 
    reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri(builder.ToString())); 
    reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword); 
    reqFTP.Method = WebRequestMethods.Ftp.UploadFile; 
    reqFTP.UsePassive = true; 
    reqFTP.UseBinary = false; 
    reqFTP.KeepAlive = false; 
    reqFTP.ContentLength = fileInf.Length; 
    reqFTP.ReadWriteTimeout = 5000; 
    reqFTP.Timeout = 5000; 

    using (ProgressDialog progressDialog = new ProgressDialog()) 
    { 
     progressDialog.backgroundWorker1.DoWork += new DoWorkEventHandler(backgroundWorker1_DoWork); 
     progressDialog.backgroundWorker1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(backgroundWorker1_RunWorkerCompleted); 
     progressDialog.backgroundWorker1.FileName = filename; 
     progressDialog.ShowDialog(); 
    } 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
    FTPBackgroundWorker worker = sender as FTPBackgroundWorker; 

    //Get file progress (if user canceled or crashed) 
    worker.NumBytesRead = GetFileProgress(worker.FileName); 
    reqFTP.ContentOffset = worker.NumBytesRead; 

    const int buffLength = 2048; 
    byte[] buff = new byte[buffLength]; 
    int contentLen; 

    using (worker.FileStream = fileInf.OpenRead()) 
    { 
     worker.FileStream.Position = worker.NumBytesRead; 
     worker.FTPStream = reqFTP.GetRequestStream(); //Exception occurs 

     while (true) 
     { 
      bool throwException = false; 
      if (worker.CancellationPending) 
      { 
       e.Cancel = true; 
       break; 
      } 

      contentLen = worker.FileStream.Read(buff, 0, buffLength); 
      if (contentLen == 0) 
       break; 

      //write file to ftp stream 
      worker.FTPStream.Write(buff, 0, contentLen); 
      worker.NumBytesRead += contentLen; 

      //For testing purposes 
      if (throwException) 
       throw new Exception("user disconnected!"); 
      worker.ReportProgress((int)(((double)worker.NumBytesRead/fileInf.Length) * 100)); 
     } 
     worker.FileStream.Close(); 
     worker.FTPStream.Close(); 
    } 
    } 

    void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
    FTPBackgroundWorker worker = sender as FTPBackgroundWorker; 
    if (e.Error != null) 
    { 
     MessageBox.Show(String.Format("Error occured uploading {0}: {1}",worker.FileName, e.Error), "Error"); 
     if (worker.FileStream != null) 
      worker.FileStream.Close(); 
     if (worker.FTPStream != null) 
      worker.FTPStream.Close(); 

     if(worker.NumBytesRead > 0) 
     { 
      MessageBox.Show("Progress has been saved", "Notification"); 
      WriteToLogFile(worker.FileName, worker.NumBytesRead); 
     } 
    } 
    else if (e.Cancelled) 
    { 
     if (worker.FileStream != null) 
      worker.FileStream.Close(); 
     if (worker.FTPStream != null) 
      worker.FTPStream.Close(); 

     MessageBox.Show("Upload Canceled", "Cancel"); 
     if (worker.NumBytesRead > 0 && MessageBox.Show("Would you like to save your upload progress?", "Notification", MessageBoxButtons.YesNo) == DialogResult.Yes) 
      WriteToLogFile(worker.FileName, worker.NumBytesRead); 
    } 
    else 
    { 
     RemoveFromLogFile(worker.FileName); 
     MessageBox.Show("Upload Complete", "Success"); 
    } 
    } 

のように見える私の質問は:ファイルパスを手放すていないサーバー側のハンドルがありますかどうかを確認し、それを削除する方法はありますか?あるいは、間違った方法で問題に近づいていますか?

おかげ

+0

こんにちは、ftpクラスでアップロードまたはダウンロード中に進捗状況をどのように実装するか尋ねることができます。 – Smith

+0

こんにちは、FTPStreamに書き込まれたバイト数を記録するのと同じくらい簡単です。私は実装のためにログに保存しました。 worker.FTPStream.Write(buff、0、contentLen); worker.NumBytesRead + = contentLen; – mthelen

+0

ありがとう、私はアップロードのために同じことをする必要があった場合、何か変更はありますか? – Smith

答えて

0

はなぜ接続が再初期化されるようにしようとする前に期限が切れるか、ユーザーが再接続を開始しようとするのを待つようになります値にタイムアウトをデクリメントしませんか?

+0

おそらくそれはおそらく最高の(そして唯一の)解決策だと思います – mthelen