Set Timeout for Webclient.Downloadfile()

Set timeout for webClient.DownloadFile()

Try WebClient.DownloadFileAsync(). You can call CancelAsync() by timer with your own timeout.

How to change the timeout on a .NET WebClient object

You can extend the timeout: inherit the original WebClient class and override the webrequest getter to set your own timeout, like in the following example.

MyWebClient was a private class in my case:

private class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri uri)
{
WebRequest w = base.GetWebRequest(uri);
w.Timeout = 20 * 60 * 1000;
return w;
}
}

Can't implement timeout when trying to download a file using WebClient.DownloadFile() or WebRequest

The timeout you implemented concerns getting Response, but not ResponseStream which contains all the data and takes usually more time to achieve. For example getting response usually takes below 1 second, but downloading content of a web page could take few seconds.

As for downloading files, you can use HttpWebRequest to get HttpWebResponse and from it use method GetResponseStream() to get the stream to the data.

This will be helpful:
Encoding trouble with HttpWebResponse

Especially the part where byte[] buffer is used to get parts of data instead of StreamReader ReadToEnd() method. While downloading parts of data to buffer you may check current DateTime against the timeout DateTime and thus allow cancelling the download after it.

Edit: a useful piece of code

private byte[] DownloadFile( string uri, int requestTimeout, int downloadTimeout, out bool isTimeout, out int bytesDownloaded )
{
HttpWebRequest request = WebRequest.Create( uri ) as HttpWebRequest;
request.Timeout = requestTimeout;
HttpWebResponse response = null;
Stream responseStream = null;
MemoryStream downloadedData = null;

byte[] result = null;
bytesDownloaded = 0;

isTimeout = false;
try
{
// Get response
response = request.GetResponse() as HttpWebResponse;
byte[] buffer = new byte[ 16384 ];

// Create buffer for downloaded data
downloadedData = new MemoryStream();

// Set the timeout
DateTime timeout = DateTime.Now.Add( new TimeSpan( 0, 0, 0, 0, downloadTimeout ) );

// Read parts of the stream
responseStream = response.GetResponseStream();
int bytesRead = 0;
DateTime now = DateTime.Now;
while ( (bytesRead = responseStream.Read( buffer, 0, buffer.Length )) > 0 && DateTime.Now < timeout )
{
downloadedData.Write( buffer, 0, bytesRead );
now = DateTime.Now;
bytesDownloaded += bytesRead;
}

// Notify if timeout occured (could've been written better)
if ( DateTime.Now >= timeout )
{
isTimeout = true;
}
}
catch ( WebException ex )
{
// Grab timeout exception
if ( ex.Status == WebExceptionStatus.Timeout )
{
isTimeout = true;
}
}
finally
{
// Close the stream
if ( responseStream != null )
{
responseStream.Close();
}
}

if ( downloadedData != null )
{
result = downloadedData.GetBuffer();
downloadedData.Close();
}

return result;
}

Usage

private void button1_Click( object sender, EventArgs e )
{
bool isTimeout;
int bytesDownloaded;
byte[] data = DownloadFile( something, 1000,500, out isTimeout, out bytesDownloaded );

MessageBox.Show( "Downloaded " + bytesDownloaded.ToString() + " bytes, Timeout = " + isTimeout.ToString() );
}

This code is still vulnerable for other exceptions you may encounter, bear that in mind.

Downloading file from url with timeout

You can create your own WebClient

public class MyWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var req = base.GetWebRequest(address);
req.Timeout = 15000;
return req;
}
}

How to implement a Timeout on WebClient.DownloadFileAsync

You can use WebClient.DownloadFileAsync(). Now inside a timer you can call CancelAsync() like so:

System.Timers.Timer aTimer = new System.Timers.Timer();
System.Timers.ElapsedEventHandler handler = null;
handler = ((sender, args)
=>
{
aTimer.Elapsed -= handler;
wc.CancelAsync();
});
aTimer.Elapsed += handler;
aTimer.Interval = 100000;
aTimer.Enabled = true;

Else create your own weclient

  public class NewWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
var req = base.GetWebRequest(address);
req.Timeout = 18000;
return req;
}
}

Set a timeout on webClient.DownloadData?

Looks like HttpWebRequest may be the way to go



Related Topics



Leave a reply



Submit