tags:

views:

1326

answers:

2

Dear all

I'm trying to cancel a downloading operation. My scenario is as follows:

When the user clicks on Cancel Download Button so this action throws exception in Download function which is as follows:

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

In the line " ftpStream.Close() " here where the exception is thrown...

The exception text is:

The remote server returned an error: (450) File unavailable (e.g., file busy)

where it opens a file to download as what i wrote " outputStream = new FileStream(filePath + "\\" + fileName, FileMode.Create);" i wont to close this stream and to close the response in order if the user did as follows: download -> cancel download -> download -> cancel download -> download

if this scenario happened the application hungs up. i don't know how to close the stream and the response so i can stop downloading then delete the created file in order to download again.

thnx

+3  A: 

The line that seems to be causing your execption is the one below and is as a result of the FTP server not finding the file you want. This is a situation that could easily happen again so it may be worth putting a try/catch block around that individual line or using a catch on the specific exception it is generating.

ftpStream = response.GetResponseStream();

At the moment in your catch block you are using outputStream.Close() but if the exception occurs on the line above then outputStream will be null. At the very least you should change the order of closing your objects in your catch block and check them for null.

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

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

if(outputStream != null) {
    outputStream.Close();
}
sipwiz
actually this way still throws an exception and it keeps saying that file is unavailablei used repFTP.Abort() but this too throws exception in retrun false step saying reqFTP is closed.actually i dont get it, i want to stop downloading and close the opened file when the user clicks on Cancel Button
Eng.Basma
Does the FTP download ever start? If you're getting the 450 response from the FTP server it seeems to inidcate it doesn't. If the download never starts calling Abort should probably be avoided.
sipwiz
no downloading process is working correctly what i ment is how 2 interrupt this process i tried all ways i said above and in some cases it gives me error?
Eng.Basma
can't i interrupt FTP process and close the file that it created FTPSTream so i can delete it where sometimes it says that this file is being used by another process
Eng.Basma
How or more importantly where in your code do you want to stop the FTP download from? From your sample the easiest place would be some kind of check for a user cancellation request in the while (readCount > 0) loop.
sipwiz
actually i dont use flags for the cancellation i just close all my streams.
Eng.Basma
as long as you close outputStream you should be able to delete the file.
sipwiz
Eng.Basma
can't any body help me in this case
Eng.Basma
I got the same problem: I start downloading a file, read the first 8k, and only proceed to download if something is in the first 8kb - problem is, if I close the ftpstream after only reading part of it, I get the same ftp error 450 on close.
Sam
+1  A: 

Ok first off, put your closes in a finally block.

So make sure your code is like this to ensure the streams get closed no matter what.

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

Wrap this line in a try catch

ftpStream = response.GetResponseStream();

This should be fine as long as those Close calls get called, where's your cancel logic? I would expect to see a flag on the loop that is set when the user clicks a button. e.g.

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);
}
Rob Stevenson-Leggett