博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[WorldWind学习]19.WebDownload
阅读量:6115 次
发布时间:2019-06-21

本文共 25105 字,大约阅读时间需要 83 分钟。

1 using System;  2 using System.Diagnostics;  3 using System.Globalization;  4 using System.Net;  5 using System.IO;  6 using System.IO.Compression;  7 using System.Threading;  8 using System.Xml;  9 using Utility; 10 using WorldWind; 11  12 namespace WorldWind.Net 13 { 14     public delegate void DownloadProgressHandler(int bytesRead, int totalBytes); 15     public delegate void DownloadCompleteHandler(WebDownload wd); 16  17     public enum DownloadType 18     { 19         Unspecified, 20         Wms 21     } 22     ///  23     /// 网络下载对象,负责下载数据 24     ///  25     public class WebDownload : IDisposable 26     { 27         #region Static proxy properties 28  29         static public bool Log404Errors = false; 30         static public bool useWindowsDefaultProxy = true; 31         static public string proxyUrl = ""; 32         static public bool useDynamicProxy; 33         static public string proxyUserName = ""; 34         static public string proxyPassword = ""; 35  36         #endregion 37         public static string UserAgent = String.Format( 38             CultureInfo.InvariantCulture, 39             "World Wind v{0} ({1}, {2})", 40             System.Windows.Forms.Application.ProductVersion, 41             Environment.OSVersion.ToString(), 42             CultureInfo.CurrentCulture.Name); 43  44         //下载连接字符串 45         public string Url; 46  47         ///  48         /// Memory downloads fills this stream 49         ///  50         public Stream ContentStream; 51  52         public string SavedFilePath; 53         public bool IsComplete; 54  55         ///  56         /// Called when data is being received.   57         /// Note that totalBytes will be zero if the server does not respond with content-length. 58         /// 开始接收数据时回调 59         /// 总的字节数为0,如果服务没有返回目录长度 60         ///  61         public DownloadProgressHandler ProgressCallback; 62  63         ///  64         /// Called to update debug window. 65         /// 更新debug窗体,回调函数 66         ///  67         public static DownloadCompleteHandler DebugCallback; 68  69         ///  70         /// Called when a download has ended with success or failure 71         /// 当下载成功或者失败时回调 72         ///  73         public static DownloadCompleteHandler DownloadEnded; 74  75         ///  76         /// Called when download is completed.  Call Verify from event handler to throw any exception. 77         /// 下载完成时回调,调用验证事件是否抛出异常。 78         ///  79         public DownloadCompleteHandler CompleteCallback; 80  81         public DownloadType DownloadType = DownloadType.Unspecified; 82         public string ContentType; 83         public int BytesProcessed; 84         public int ContentLength; 85  86         // variables to allow placefinder to use gzipped requests 87         //  *default to uncompressed requests to avoid breaking other things 88         public bool Compressed = false; 89         public string ContentEncoding; 90  91         ///  92         /// The download start time (or MinValue if not yet started) 93         ///  94         public DateTime DownloadStartTime = DateTime.MinValue; 95  96         internal HttpWebRequest request; 97         internal HttpWebResponse response; 98  99         protected Exception downloadException;100 101         protected bool isMemoryDownload;102         /// 103         /// used to signal thread abortion; if true, the download thread was aborted104         /// 105         private bool stopFlag = false;106         //下载线程107         protected Thread dlThread;108 109         /// 110         /// Initializes a new instance of the 
class.111 /// 构造函数,初始化下载对象112 ///
113 /// The URL to download from.114 public WebDownload(string url)115 {116 this.Url = url;117 }118 119 /// 120 /// Initializes a new instance of the
class.121 ///
122 public WebDownload()123 {124 }125 126 /// 127 /// Whether the download is currently being processed (active).128 /// 当前下载是否仍在进行129 /// 130 public bool IsDownloadInProgress131 {132 get133 {134 return dlThread != null && dlThread.IsAlive;135 }136 }137 138 /// 139 /// Contains the exception that occurred during download, or null if successful.140 /// 141 public Exception Exception142 {143 get144 {145 return downloadException;146 }147 }148 149 /// 150 /// Asynchronous download of HTTP data to file. 151 /// 异步下载Http数据,通过开启新线程实现。152 /// 153 public void BackgroundDownloadFile()154 {155 if (CompleteCallback == null)156 throw new ArgumentException("No download complete callback specified.");157 //实例化下载线程158 dlThread = new Thread(new ThreadStart(Download));159 dlThread.Name = "WebDownload.dlThread";160 dlThread.IsBackground = true;161 dlThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;162 //开启后台下载线程163 dlThread.Start();164 }165 166 /// 167 /// Asynchronous download of HTTP data to file.168 /// 异步下载Http数据,绑定下载完成后的回调函数。169 /// 170 public void BackgroundDownloadFile(DownloadCompleteHandler completeCallback)171 {172 CompleteCallback += completeCallback;173 BackgroundDownloadFile();174 }175 176 /// 177 /// Download image of specified type. (handles server errors for wms type)178 /// 179 public void BackgroundDownloadFile(DownloadType dlType)180 {181 DownloadType = dlType;182 BackgroundDownloadFile();183 }184 185 /// 186 /// Asynchronous download of HTTP data to in-memory buffer.187 /// 异步下载Http数据到内存缓冲区188 /// 189 public void BackgroundDownloadMemory()190 {191 if (CompleteCallback == null)192 throw new ArgumentException("No download complete callback specified.");193 194 isMemoryDownload = true;195 dlThread = new Thread(new ThreadStart(Download));196 dlThread.Name = "WebDownload.dlThread(2)";197 dlThread.IsBackground = true;198 dlThread.CurrentUICulture = Thread.CurrentThread.CurrentUICulture;199 dlThread.Start();200 }201 202 /// 203 /// Asynchronous download of HTTP data to in-memory buffer. 204 /// 205 public void BackgroundDownloadMemory(DownloadCompleteHandler completeCallback)206 {207 CompleteCallback += completeCallback;208 BackgroundDownloadMemory();209 }210 211 /// 212 /// Download image of specified type. (handles server errors for WMS type)213 /// 214 /// Type of download.215 public void BackgroundDownloadMemory(DownloadType dlType)216 {217 DownloadType = dlType;218 BackgroundDownloadMemory();219 }220 221 /// 222 /// Synchronous download of HTTP data to in-memory buffer. 223 /// 224 public void DownloadMemory()225 {226 isMemoryDownload = true;227 Download();228 }229 230 /// 231 /// Download image of specified type. (handles server errors for WMS type)232 /// 233 public void DownloadMemory(DownloadType dlType)234 {235 DownloadType = dlType;236 DownloadMemory();237 }238 239 /// 240 /// HTTP downloads to memory.241 /// 242 /// The progress callback.243 public void DownloadMemory(DownloadProgressHandler progressCallback)244 {245 ProgressCallback += progressCallback;246 DownloadMemory();247 }248 249 /// 250 /// Synchronous download of HTTP data to in-memory buffer. 251 /// 252 public void DownloadFile(string destinationFile)253 {254 SavedFilePath = destinationFile;255 256 Download();257 }258 259 /// 260 /// Download image of specified type to a file. (handles server errors for WMS type)261 /// 262 public void DownloadFile(string destinationFile, DownloadType dlType)263 {264 DownloadType = dlType;265 DownloadFile(destinationFile);266 }267 268 /// 269 /// Saves a http in-memory download to file.270 /// 271 /// File to save the downloaded data to.272 public void SaveMemoryDownloadToFile(string destinationFilePath)273 {274 if (ContentStream == null)275 throw new InvalidOperationException("No data available.");276 277 // Cache the capabilities on file system278 ContentStream.Seek(0, SeekOrigin.Begin);279 using (Stream fileStream = File.Create(destinationFilePath))280 {281 if (ContentStream is MemoryStream)282 {283 // Write the MemoryStream buffer directly (2GB limit)284 MemoryStream ms = (MemoryStream)ContentStream;285 fileStream.Write(ms.GetBuffer(), 0, (int)ms.Length);286 }287 else288 {289 // Block copy290 byte[] buffer = new byte[4096];291 while (true)292 {293 int numRead = ContentStream.Read(buffer, 0, buffer.Length);294 if (numRead <= 0)295 break;296 fileStream.Write(buffer, 0, numRead);297 }298 }299 }300 ContentStream.Seek(0, SeekOrigin.Begin);301 }302 303 /// 304 /// Aborts the current download. 305 /// 终止当前下载306 /// 307 public void Cancel()308 {309 CompleteCallback = null;310 ProgressCallback = null;311 if (dlThread != null && dlThread != Thread.CurrentThread)312 {313 if (dlThread.IsAlive)314 {315 Log.Write(Log.Levels.Verbose, "WebDownload.Cancel() : stopping download thread...");316 stopFlag = true;317 if (!dlThread.Join(500))318 {319 Log.Write(Log.Levels.Warning, "WebDownload.Cancel() : download thread refuses to die, forcing Abort()");320 dlThread.Abort();321 }322 }323 dlThread = null;324 }325 }326 327 /// 328 /// Notify event subscribers of download progress.329 /// 330 /// Number of bytes read.331 /// Total number of bytes for request or 0 if unknown.332 private void OnProgressCallback(int bytesRead, int totalBytes)333 {334 if (ProgressCallback != null)335 {336 ProgressCallback(bytesRead, totalBytes);337 }338 }339 340 /// 341 /// Called with detailed information about the download.342 /// 343 /// The WebDownload.344 private static void OnDebugCallback(WebDownload wd)345 {346 if (DebugCallback != null)347 {348 DebugCallback(wd);349 }350 }351 352 /// 353 /// Called when downloading has ended.354 /// 355 /// The download.356 private static void OnDownloadEnded(WebDownload wd)357 {358 if (DownloadEnded != null)359 {360 DownloadEnded(wd);361 }362 }363 364 /// 365 /// Synchronous HTTP download366 /// 线程异步调用的方法Download中,采用请求响应同步下载数据367 /// 368 protected void Download()369 {370 Log.Write(Log.Levels.Debug, "Starting download thread...");371 372 Debug.Assert(Url.StartsWith("http://"));373 DownloadStartTime = DateTime.Now;374 try375 {376 try377 {378 // If a registered progress-callback, inform it of our download progress so far.379 OnProgressCallback(0, 1);380 OnDebugCallback(this);381 382 // check to see if thread was aborted (multiple such checks within the thread function)383 if (stopFlag)384 {385 IsComplete = true;386 return;387 }388 389 390 // create content stream from memory or file391 if (isMemoryDownload && ContentStream == null)392 {393 ContentStream = new MemoryStream();394 }395 else396 {397 // Download to file398 string targetDirectory = Path.GetDirectoryName(SavedFilePath);399 if (targetDirectory.Length > 0)400 Directory.CreateDirectory(targetDirectory);401 ContentStream = new FileStream(SavedFilePath, FileMode.Create);402 }403 404 // Create the request object.405 request = (HttpWebRequest)WebRequest.Create(Url);406 request.UserAgent = UserAgent;407 408 409 if (this.Compressed)410 {411 request.Headers.Add("Accept-Encoding", "gzip,deflate");412 }413 if (stopFlag)414 {415 IsComplete = true;416 return;417 }418 request.Proxy = ProxyHelper.DetermineProxyForUrl(419 Url,420 useWindowsDefaultProxy,421 useDynamicProxy,422 proxyUrl,423 proxyUserName,424 proxyPassword);425 426 // TODO: probably better done via BeginGetResponse() / EndGetResponse() because this may block for a while427 // causing warnings in thread abortion.428 using (response = request.GetResponse() as HttpWebResponse)429 {430 // only if server responds 200 OK431 if (response.StatusCode == HttpStatusCode.OK)432 {433 ContentType = response.ContentType;434 ContentEncoding = response.ContentEncoding;435 436 // Find the data size from the headers.437 string strContentLength = response.Headers["Content-Length"];438 if (strContentLength != null)439 {440 ContentLength = int.Parse(strContentLength, CultureInfo.InvariantCulture);441 }442 //缓存字节数组,大小1500byte443 byte[] readBuffer = new byte[1500];444 using (Stream responseStream = response.GetResponseStream())445 {446 while (true)447 {448 if (stopFlag)449 {450 IsComplete = true;451 return;452 }453 454 // Pass do.readBuffer to BeginRead.455 int bytesRead = responseStream.Read(readBuffer, 0, readBuffer.Length);456 if (bytesRead <= 0)457 break;458 459 //TODO: uncompress responseStream if necessary so that ContentStream is always uncompressed460 // - at the moment, ContentStream is compressed if the requesting code sets461 // download.Compressed == true, so ContentStream must be decompressed 462 // by whatever code is requesting the gzipped download463 // - this hack only works for requests made using the methods that download to memory,464 // requests downloading to file will result in a gzipped file465 // - requests that do not explicity set download.Compressed = true should be unaffected466 467 ContentStream.Write(readBuffer, 0, bytesRead);468 469 BytesProcessed += bytesRead;470 471 // If a registered progress-callback, inform it of our download progress so far.472 OnProgressCallback(BytesProcessed, ContentLength);473 OnDebugCallback(this);474 }475 }476 477 }478 }479 480 HandleErrors();481 }482 catch (ThreadAbortException)483 {484 // re-throw to avoid it being caught by the catch-all below485 Log.Write(Log.Levels.Verbose, "Re-throwing ThreadAbortException.");486 throw;487 }488 catch (System.Configuration.ConfigurationException)489 {490 // is thrown by WebRequest.Create if App.config is not in the correct format491 // TODO: don't know what to do with it492 throw;493 }494 catch (Exception caught)495 {496 try497 {498 // Remove broken file download499 if (ContentStream != null)500 {501 ContentStream.Close();502 ContentStream = null;503 }504 if (SavedFilePath != null && SavedFilePath.Length > 0)505 {506 File.Delete(SavedFilePath);507 }508 }509 catch (Exception)510 {511 }512 SaveException(caught);513 }514 515 if (stopFlag)516 {517 IsComplete = true;518 return;519 }520 521 if (ContentLength == 0)522 {523 ContentLength = BytesProcessed;524 // If a registered progress-callback, inform it of our completion525 OnProgressCallback(BytesProcessed, ContentLength);526 }527 528 if (ContentStream is MemoryStream)529 {530 ContentStream.Seek(0, SeekOrigin.Begin);531 }532 else if (ContentStream != null)533 {534 ContentStream.Close();535 ContentStream = null;536 }537 538 OnDebugCallback(this);539 540 if (CompleteCallback == null)541 {542 Verify();543 }544 else545 {546 CompleteCallback(this);547 }548 }549 catch (ThreadAbortException)550 {551 Log.Write(Log.Levels.Verbose, "Download aborted.");552 }553 finally554 {555 IsComplete = true;556 }557 558 OnDownloadEnded(this);559 }560 561 /// 562 /// Handle server errors that don't get trapped by the web request itself.563 /// 564 private void HandleErrors()565 {566 // HACK: Workaround for TerraServer failing to return 404 on not found567 if (ContentStream.Length == 15)568 {569 // a true 404 error is a System.Net.WebException, so use the same text here570 Exception ex = new FileNotFoundException("The remote server returned an error: (404) Not Found.", SavedFilePath);571 SaveException(ex);572 }573 574 // TODO: WMS 1.1 content-type != xml575 // TODO: Move WMS logic to WmsDownload576 if (DownloadType == DownloadType.Wms && (577 ContentType.StartsWith("text/xml") ||578 ContentType.StartsWith("application/vnd.ogc.se")))579 {580 // WMS request failure581 SetMapServerError();582 }583 }584 585 /// 586 /// If exceptions occurred they will be thrown by calling this function.587 /// 588 public void Verify()589 {590 if (Exception != null)591 throw Exception;592 }593 594 /// 595 /// Log download error to log file596 /// 597 /// 598 private void SaveException(Exception exception)599 {600 // Save the exception 601 downloadException = exception;602 603 if (Exception is ThreadAbortException)604 // Don't log canceled downloads605 return;606 607 if (Log404Errors)608 {609 Log.Write(Log.Levels.Error, "HTTP", "Error: " + Url);610 Log.Write(Log.Levels.Error + 1, "HTTP", " : " + exception.Message);611 }612 }613 614 /// 615 /// Reads the xml response from the server and throws an error with the message.616 /// 617 private void SetMapServerError()618 {619 try620 {621 XmlDocument errorDoc = new XmlDocument();622 ContentStream.Seek(0, SeekOrigin.Begin);623 errorDoc.Load(ContentStream);624 string msg = "";625 foreach (XmlNode node in errorDoc.GetElementsByTagName("ServiceException"))626 msg += node.InnerText.Trim() + Environment.NewLine;627 SaveException(new WebException(msg.Trim()));628 }629 catch (XmlException)630 {631 SaveException(new WebException("An error occurred while trying to download " + request.RequestUri.ToString() + "."));632 }633 }634 635 #region IDisposable Members636 637 /// 638 /// Performs application-defined tasks associated with freeing, releasing, or639 /// resetting unmanaged resources.640 /// 641 public void Dispose()642 {643 if (dlThread != null && dlThread != Thread.CurrentThread)644 {645 if (dlThread.IsAlive)646 {647 Log.Write(Log.Levels.Verbose, "WebDownload.Dispose() : stopping download thread...");648 stopFlag = true;649 if (!dlThread.Join(500))650 {651 Log.Write(Log.Levels.Warning, "WebDownload.Dispose() : download thread refuses to die, forcing Abort()");652 dlThread.Abort();653 }654 }655 dlThread = null;656 }657 658 if (request != null)659 {660 request.Abort();661 request = null;662 }663 664 if (ContentStream != null)665 {666 ContentStream.Close();667 ContentStream = null;668 }669 670 if (DownloadStartTime != DateTime.MinValue)671 OnDebugCallback(this);672 673 GC.SuppressFinalize(this);674 }675 #endregion676 }677 }
View Code

该类基于Http协议,应用层。

Socket有两种:流式Socket(SOCK_STREAM)和数据报式Socket(SOCK_DGRAM)。传输层

  流式是一种面向连接的Socket,针对于面向连接的TCP服务应用;

  数据报式Socket是一种无连接的Socket,对应于无连接的UDP服务应用。

转载于:https://www.cnblogs.com/yhlx125/p/3334568.html

你可能感兴趣的文章
Oracle表分区
查看>>
centos 下安装g++
查看>>
嵌入式,代码调试----GDB扫盲
查看>>
类斐波那契数列的奇妙性质
查看>>
配置设置[Django]引入模版之后报错Requested setting TEMPLATE_DEBUG, but settings are not configured....
查看>>
下一步工作分配
查看>>
Response. AppendHeader使用大全及文件下载.net函数使用注意点(转载)
查看>>
Wait Functions
查看>>
代码描述10313 - Pay the Price
查看>>
jQuery最佳实践
查看>>
centos64i386下apache 403没有权限访问。
查看>>
vb sendmessage 详解1
查看>>
jquery用法大全
查看>>
Groonga 3.0.8 发布,全文搜索引擎
查看>>
PC-BSD 9.2 发布,基于 FreeBSD 9.2
查看>>
网卡驱动程序之框架(一)
查看>>
css斜线
查看>>
Windows phone 8 学习笔记(3) 通信
查看>>
重新想象 Windows 8 Store Apps (18) - 绘图: Shape, Path, Stroke, Brush
查看>>
Revit API找到风管穿过的墙(当前文档和链接文档)
查看>>