0

I have an application for download Zip files from an FTP.

Many times I got connection problems while a file is downloading so I have to retry but I can't do it.

When I try to download de file again with this line "reader = response.GetResponseStream();" I got the follow messagge "The process cannot access the file xxx because it is being used by another process". I decided to close the writer stream (memStream) in the catch and sometimes it works but sometimes when I try to get de respose again it doesn't work a give me a time out exception.

Is there an clear way to retry download a file from FTP without errors?

EDIT: I see that I can start download again the first file that fail but when another file fail I can't get the response from the request and gimme the time out

Here is the code:

FtpWebResponse response = null;
FtpWebRequest request = null;
Stream memStream = null;
Stream reader = null;
Directory.CreateDirectory(pathDestino);

                try
                {
                    request = FtpWebRequest.Create(urlArchivo) as FtpWebRequest;
                    request.Credentials = new NetworkCredential("ftp", "ftp");


                //Now get the actual data
                request = FtpWebRequest.Create(urlArchivo) as FtpWebRequest;
                request.Method = WebRequestMethods.Ftp.DownloadFile;
                request.Credentials = new NetworkCredential("ftp", "ftp");
                request.UsePassive = true;
                request.UseBinary = true;
                request.KeepAlive = false; //close the connection when done
                if(totalBytes!=0)  //check if a file failed
                {
                    request.ContentOffset=totalBytes;
                }
                //Streams
                response = request.GetResponse() as FtpWebResponse;
                reader = response.GetResponseStream();
                //Download to memory
                //Note: adjust the streams here to download directly to the hard drive
                //MemoryStream memStream = new MemoryStream();
                string pathCompleto = pathDestino + @"\" + horaMinuto + ".zip";
                memStream = File.Create(pathCompleto);
                byte[] buffer = new byte[1024]; //downloads in chuncks
                int bytesAcum = 0;
                while (true)
                {

                    int bytesRead = reader.Read(buffer, 0, buffer.Length);

                    if (bytesRead == 0)
                    {                        
                        break;
                    }
                    else
                    {
                        //Write the downloaded data
                        memStream.Write(buffer, 0, bytesRead);
                        totalBytes=+bytesRead;
                    }
                }

                //Convert the downloaded stream to a byte array
                //downloadedData = memStream.ToArray();

                //Clean up
                reader.Close();
                memStream.Close();
                response.Close();
                totalBytes=0;

            }

catch
{
//something
memStream.Close();
request.Abort();
}

1 Answers1

0

Typically "resume" in FTP involves requesting the file again from a specific file byte offset.

Looking at FtpWebRequest class, the property you need to populate once the connection fails will be the length of your already downloaded buffer and you should set the property ContentOffset.

More information on this property at the link: http://msdn.microsoft.com/en-us/library/system.net.ftpwebrequest.contentoffset(v=vs.110).aspx

toadflakz
  • 7,764
  • 1
  • 27
  • 40
  • Thanks. How can I implement it? I have to close both streams and response and them works like if I start again but using te contentoffset? – Emiliano Magnani Efisat Nov 27 '14 at 17:35
  • There is code under the link to show you how. Yes, you would need to construct new Request/Response object pairs - this is just the way these classes work, unfortunately. – toadflakz Nov 27 '14 at 22:49
  • I tried it and got the same error. It looks like some connection wasn't closed and when I tried to get a new response it can't be performed. If I stop running my application and open it again, everything start to work ok. – Emiliano Magnani Efisat Nov 28 '14 at 11:49
  • How did you close and reopen the connection? Still using the `response` and `request` variables like in the code above? If so, did you call `Close()` on both the response stream and the response before reassigning? – toadflakz Nov 28 '14 at 14:56
  • Yes, I close the streams and response in the try but I can't close the reader stream and the response in the catch(I can't use finally for this reason) because an exception tell me that they are closed. I tried request.abort() after writer.close() in the catch and it worked!! Now my problem is trying to resume de download, when I try to unzip I can't because the zip is corrupted. I think I am setting the wrong ContentOffset. Can u help me? – Emiliano Magnani Efisat Nov 28 '14 at 18:02
  • You should update the question with the new code that's partly working. ;-) – toadflakz Nov 28 '14 at 19:13