Download and Unpack a zip from an FTP server with recovery - icsharpcode/SharpZipLib GitHub Wiki
Code Reference / Zip Samples / Download and Unpack a zip from an FTP server with recovery
This example extends upon Unpack a zip using ZipInputStream, to provide for a recoverable FTP download and extract.
C#
public class FtpSample
{
public static void TestZipDownload()
{
// Create the FTP stream that takes care of restarting in event of failure.
// This will hide any temporary problems from ZipInputStream
using(var ftpStream = new FtpDownloadStream(
serverUri: "ftp://www.contoso.com/test.htm",
userName: "anonymous",
password: "[email protected]"
))
{
UnzipFromStream(ftpStream, @"c:\temp\out");
}
}
// Insert the "UnzipFromStream" code from the sample mentioned
}
// Implements a restartable Ftp Download and exposes the result as an uninterrupted stream.
public class FtpDownloadStream : Stream
{
private string _serverUri;
private string _userName;
private string _password;
private FtpWebRequest _request;
private FtpWebResponse _response;
private Stream _responseStream;
private int _totalDone;
public Exception CaughtException;
public FtpDownloadStream(string serverUri, string userName, string password)
{
_serverUri = serverUri;
_userName = userName;
_password = password;
}
private void StartFtpDownload()
{
// This can be replaced with the Http equivalents
_request = WebRequest.Create(_serverUri) as FtpWebRequest;
_request.Method = WebRequestMethods.Ftp.DownloadFile;
_request.Credentials = new NetworkCredential(_userName, _password);
_request.ContentOffset = _totalDone; // for resume on failure
_response = (FtpWebResponse)_request.GetResponse();
_responseStream = _response.GetResponseStream();
//if (_responseStream != null)
// _responseStream.ReadTimeout = 10000; // Set timeout to 10 seconds for testing.
}
public override int Read(byte[] buffer, int offset, int count)
{
int attempts = 0;
// Adjust the maximum attempts according to your needs
while (attempts++ < 5)
{
if (_responseStream == null)
{
StartFtpDownload();
}
try
{
// This will throw a timeout exception if the connection is interrupted.
// Will throw null exception if failed to open (start); this will also retry.
int done = _responseStream.Read(buffer, offset, count);
_totalDone += done;
return done;
}
catch (Exception ex)
{
CaughtException = ex;
// Close ftp resources if possible. Set instances to null to force restart.
Close();
}
}
return 0;
}
public override void Close()
{
if (_responseStream != null)
{
try
{
_responseStream.Close();
_response.Close();
}
catch
{
// No action required
}
}
_responseStream = null;
_response = null;
_request = null;
}
// Implement the Stream methods
public override void Flush()
=> throw new NotImplementedException();
public override long Seek(long offset, SeekOrigin origin)
=> throw new NotImplementedException();
public override void SetLength(long value)
=> throw new NotImplementedException();
public override void Write(byte[] buffer, int offset, int count)
=> throw new NotImplementedException();
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => throw new NotImplementedException();
public override long Position {
get => throw new NotImplementedException();
set => throw new NotImplementedException();
}
}