Ошибка при закрытии ftp-потока в C#

Я пытаюсь отменить операцию загрузки. Мой сценарий выглядит следующим образом:

Когда пользователь нажимает кнопку «Отменить загрузку», это действие вызывает исключение в функции загрузки, которое выглядит следующим образом:

        try
        {
            reqFTP = (FtpWebRequest)FtpWebRequest.Create(new Uri("ftp://" + uri + "/" + fileName));
            reqFTP.Method = WebRequestMethods.Ftp.DownloadFile;
            reqFTP.UseBinary = true;
            reqFTP.Credentials = new NetworkCredential(ftpUserID, ftpPassword);
            reqFTP.UsePassive = true;

            response = (FtpWebResponse)reqFTP.GetResponse();
            ftpStream = response.GetResponseStream();
            _isItOutputStream = true;
            string dataLengthString = response.Headers["Content-Length"];
            int dataLength = 0;
            if (dataLengthString != null)
            {
                dataLength = Convert.ToInt32(dataLengthString);
            }

            long cl = response.ContentLength;
            int bufferSize = 4048;
            int readCount;
            byte[] buffer = new byte[bufferSize];
            readCount = ftpStream.Read(buffer, 0, bufferSize);
            outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);
            bool first = true;
            while (readCount > 0)
            {
                outputStream.Write(buffer, 0, readCount);
                _actualDownloaded += readCount;
                if (this.InvokeRequired)
                {
                    ProgressBarDel _progressDel = new ProgressBarDel(ProgressBar);
                    this.Invoke(_progressDel, new object[] { _actualDownloaded, first });
                }
                first = false;
                readCount = ftpStream.Read(buffer, 0, bufferSize);
            }
            ftpStream.Close();
            outputStream.Close();
            response.Close();
            _isItOutputStream = false;
            return true;
        }
        catch (Exception ee)
        {
            _downloadException = ee.Message;
            if (response != null)
            {

                outputStream.Close();
                ftpStream.Close();
                response.Close();
            }
            return false;
        }

В строке "ftpStream.Close()" здесь возникает исключение...

Текст исключения:

Удаленный сервер вернул ошибку: (450) Файл недоступен (например, файл занят)

где он открывает файл для загрузки, как я написал "outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);", я не буду закрывать этот поток и закрывать ответ, если пользователь сделал следующее: загрузить -> отменить загрузку -> загрузить -> отменить загрузку -> загрузить

если этот сценарий произошел, приложение зависло. я не знаю, как закрыть поток и ответ, чтобы я мог остановить загрузку, а затем удалить созданный файл, чтобы загрузить его снова.

спасибо


person BDeveloper    schedule 26.03.2009    source источник
comment
проблема в том, что когда я повторно загружаю сообщение, появляется сообщение о том, что этот файл используется (потому что я отменил предыдущую загрузку, а затем снова попытался загрузить)   -  person BDeveloper    schedule 12.04.2009
comment
Получил аналогичную ошибку (загрузка файлов, после загрузки при закрытии () я получаю ошибку ftp 450). Вы нашли решение своей проблемы?   -  person Sam    schedule 10.07.2009


Ответы (2)


Строка, которая, кажется, вызывает ваше исключение, приведена ниже и является результатом того, что FTP-сервер не нашел нужный файл. Это ситуация, которая может легко повториться, поэтому, возможно, стоит поместить блок try/catch вокруг этой отдельной строки или использовать блокировку для конкретного исключения, которое она генерирует.

ftpStream = response.GetResponseStream();

На данный момент в вашем блоке catch вы используете outputStream.Close(), но если исключение возникает в строке выше, тогда outputStream будет нулевым. По крайней мере, вы должны изменить порядок закрытия ваших объектов в блоке catch и проверить их на нуль.

if(response != null) {
    response.Close();
}

if(ftpStream != null) {
    ftpStream.Close();
}

if(outputStream != null) {
    outputStream.Close();
}
person sipsorcery    schedule 26.03.2009
comment
на самом деле этот способ по-прежнему выдает исключение, и он продолжает говорить, что файл недоступен, я использовал repFTP.Abort(), но это тоже выдает исключение при повторном запуске ложного шага, говорящего, что reqFTP закрыт. на самом деле я не понимаю, я хочу остановить загрузку и закрыть открытый файл, когда пользователь нажимает кнопку «Отмена» - person BDeveloper; 26.03.2009
comment
Загрузка по FTP когда-нибудь начинается? Если вы получаете ответ 450 от FTP-сервера, кажется, что это не так. Если загрузка так и не начинается, вызова Abort, вероятно, следует избегать. - person sipsorcery; 27.03.2009
comment
ни один процесс загрузки не работает правильно, что я имею в виду, как 2 прервать этот процесс, я пробовал все способы, которые я сказал выше, и в некоторых случаях это дает мне ошибку? - person BDeveloper; 28.03.2009
comment
я не могу прервать процесс FTP и закрыть файл, который он создал FTPSTream, чтобы я мог удалить его, когда иногда он говорит, что этот файл используется другим процессом - person BDeveloper; 28.03.2009
comment
Как или, что более важно, где в вашем коде вы хотите остановить загрузку по FTP? Из вашего примера самым простым местом будет какая-то проверка запроса отмены пользователя в цикле while (readCount › 0). - person sipsorcery; 28.03.2009
comment
на самом деле я не использую флаги для отмены, я просто закрываю все свои потоки. - person BDeveloper; 12.04.2009
comment
пока вы закроете outputStream, вы сможете удалить файл. - person sipsorcery; 12.04.2009
comment
хотя я добавил флаг в свой цикл while (readCount › 0 && !cancelClicked), а также добавил блоки try{} catch{} и finally{}, он все равно выдает ошибку при достижении статуса outputStream.Close(), который находится в finally блок и ошибка Удаленный сервер вернул ошибку: (450) Файл недоступен - person BDeveloper; 12.04.2009
comment
никто не может помочь мне в этом случае - person BDeveloper; 11.06.2009
comment
У меня такая же проблема: я начинаю скачивать файл, читаю первые 8k и продолжаю скачивать, только если что-то находится в первых 8kb - проблема в том, что если я закрываю ftpstream после чтения только его части, я получаю тот же ftp ошибка 450 при закрытии. - person Sam; 10.07.2009

Хорошо, во-первых, поместите ваши закрытия в блок finally.

Поэтому убедитесь, что ваш код такой, чтобы гарантировать закрытие потоков, несмотря ни на что.

try
{
   //Your existing logic
   //Don't need to close the streams/etc
}
catch
{
   //Just do what you need to with the exception
}
finally
{
   //This is always called
   if (response != null)
      response.Close();
   if(outputStream != null)
      outputStream.Close();
   if(ftpStream != null)
      ftpStream.Close();
} 

Оберните эту строку в попытке поймать

ftpStream = response.GetResponseStream();

Это должно быть хорошо, пока эти вызовы Close вызываются, где ваша логика отмены? Я ожидаю увидеть флаг в цикле, который устанавливается, когда пользователь нажимает кнопку. например

while (readCount > 0 && !_shouldExit)
{
   outputStream.Write(buffer, 0, readCount);
  _actualDownloaded += readCount;
  if (this.InvokeRequired)
  {
    ProgressBarDel _progressDel = new ProgressBarDel(ProgressBar);
    this.Invoke(_progressDel, new object[] { _actualDownloaded, first });
  }
  first = false;
  readCount = ftpStream.Read(buffer, 0, bufferSize);
}
person Rob Stevenson-Leggett    schedule 26.03.2009