断开连接后的FtpWebRequest.GetRequestStream()

时间:2011-09-23 13:43:27

标签: .net ftp ftpwebrequest

我正在为一个ftp实用程序进行原型设计,该实用程序将保存用户的进度,并且如果他们的互联网断开连接,则从他们开始的位置重新上传给定文件。 (它适用于连接速度较慢的客户端。)

想法是打开文件流和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");
     }
  }

我的问题是:有没有办法检查服务器端是否有一个不放弃文件路径并删除它的句柄?或者我用错误的方法来解决问题?

由于

1 个答案:

答案 0 :(得分:0)

为什么不将超时减少到在连接尝试再次初始化之前到期的值,或者让用户等待再次尝试启动连接?