tags:

views:

316

answers:

1

Dear all, one my application features is tod download files from our ftp server. And of course this feature reqiures to cancel this operation (Cancel Downloading).

Now, my Download Function 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 (ftpStream != null && outputStream!=null )
                    if (ftpStream.CanRead && outputStream.CanWrite)
                    {
                        ftpStream.Close();
                        outputStream.Close();
                    }

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

                return false;
            }

Now as you can see in Catch Block you can see that i'm trying to interrupt this connection when the user clicks on Cancel button.

  • Canceling Operation Scenario:

1) Cancel button was clicked.

2) Call Function "DoSomeWorx()"

3) in "DoSomeWorx()" do:

if (_isItOutputStream)// where here i'm trying to check if it's downloading 
 {
   ftpStream.Close();
   outputStream.Close();
   response.Close(); 
 }
 if (_startCopy)// check if copying to phone 
 {
   IsCancelled();
 }
 _btnDownload2PhoneThread.Abort(); // actually this operation does what i did before but for some resoans it does this but it takes time...
 _btnDownload2PhoneThread.Join();

The Problem is when i reach any of these statments (ftpStream.Close();outputStream.Close();response.Close();) it throws an exception "File unavailable(e.g file is busy)"

and this exception affects on re-downloading operation where it sees the file busy.

so how to avoid this exception?

+2  A: 

I'm assuming that you have a form of some sort, so your performing the download on a thread.

What your probably better off doing is checking a "cancel" flag inside your while loop.

eg.

while(readcount > 0 && !cancel)
{
   ...
}

Then let your method gracefully cancel out.

Secondly you should use a using statement on your streams. That means that if you throw an exception, the finally block will guarantee that your stream gets disposed (which incidentally is why you would be receiving file busy, as the stream hasn't yet had it's destructor run, even though your method has completed)

Spence
i added the flag to my loop but still when it reaches to outputStream.Close of response.close(); or ftpStream.close() statment it throws an exception says that the file is unavailable (e.g file is busy)
Eng.Basma
Did you remove the code touching streams in your "cancel" method? Remove the thread abort, and and "try" to join the thread. If it takes too long, you may want to abort it then.Secondly, which line is throwing the exception. If you look at the details of the exception it will tell you.
Spence