我正在尝试实现一些从URL下载文件的功能。但是,如果文件花费的时间超过30秒,我想取消下载或使其超时。
我尝试重写WebClient类以实现超时,但是无论我将超时设置为什么值,它都永远不会超时!这是我尝试过的代码,可在另一个stackoverflow答案中找到:
using System;
using System.Net;
public class WebDownload : WebClient
{
/// <summary>
/// Time in milliseconds
/// </summary>
public int Timeout { get; set; }
public WebDownload() : this(60000) { }
public WebDownload(int timeout)
{
this.Timeout = timeout;
}
protected override WebRequest GetWebRequest(Uri address)
{
var request = base.GetWebRequest(address);
if (request != null)
{
request.Timeout = this.Timeout;
}
return request;
}
}
然后,使用调用:
WebDownload webClient = new WebDownload(20000);
try
{
webClient.DownloadFile(url, tmpFile);
}
catch {
//throw error
}
我也尝试过使用WebRequest方法下载文件,并使用Timeout和ReadWriteTimeout属性,但是没有骰子。这必须是一个非常普遍的用例。任何帮助表示赞赏。谢谢!
您实现的超时关系到获取Response,而不是响应Stream,因为它包含所有数据并且通常花费更多时间来实现。例如,获取响应通常需要不到1秒,但是下载网页内容可能需要几秒钟。
至于下载文件,您可以使用HttpWebRequest
getHttpWebResponse
方法和从中使用use方法GetResponseStream()
将流获取到数据。
这将是有帮助的:HttpWebResponse的编码问题
尤其byte[] buffer
是用于获取数据部分而不是StreamReader
ReadToEnd()
方法的部分。在下载部分数据以缓冲时,您可以对照超时日期时间检查当前日期时间,从而允许在其之后取消下载。
编辑:一段有用的代码
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;
}
用法
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() );
}
请记住,此代码仍然容易受到您可能遇到的其他异常的影响。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句