FtpWebRequest.GetRequestStream () после отключения - PullRequest
1 голос
/ 23 сентября 2011

Я создаю прототип утилиты 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 голосов
/ 13 февраля 2012

Почему бы не уменьшить время ожидания до значения, которое истечет до повторной инициализации соединения или не заставит пользователя ждать, чтобы попытаться установить соединение снова?

...