PageRenderTime 30ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

/mcs/class/System/System.Net/WebClient.cs

https://bitbucket.org/foobar22/mono
C# | 2210 lines | 1803 code | 305 blank | 102 comment | 422 complexity | b6c99c4f0814089ddc393e2fcdf55937 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, CC-BY-SA-3.0, GPL-2.0, Unlicense, Apache-2.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. //
  2. // System.Net.WebClient
  3. //
  4. // Authors:
  5. // Lawrence Pit (loz@cable.a2000.nl)
  6. // Gonzalo Paniagua Javier (gonzalo@ximian.com)
  7. // Atsushi Enomoto (atsushi@ximian.com)
  8. // Miguel de Icaza (miguel@ximian.com)
  9. // Martin Baulig (martin.baulig@googlemail.com)
  10. // Marek Safar (marek.safar@gmail.com)
  11. //
  12. // Copyright 2003 Ximian, Inc. (http://www.ximian.com)
  13. // Copyright 2006, 2010 Novell, Inc. (http://www.novell.com)
  14. // Copyright 2012 Xamarin Inc. (http://www.xamarin.com)
  15. //
  16. //
  17. // Permission is hereby granted, free of charge, to any person obtaining
  18. // a copy of this software and associated documentation files (the
  19. // "Software"), to deal in the Software without restriction, including
  20. // without limitation the rights to use, copy, modify, merge, publish,
  21. // distribute, sublicense, and/or sell copies of the Software, and to
  22. // permit persons to whom the Software is furnished to do so, subject to
  23. // the following conditions:
  24. //
  25. // The above copyright notice and this permission notice shall be
  26. // included in all copies or substantial portions of the Software.
  27. //
  28. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  29. // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  30. // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  31. // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  32. // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  33. // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  34. // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  35. //
  36. //
  37. // Notes on CancelAsync and Async methods:
  38. //
  39. // WebClient.CancelAsync is implemented by calling Thread.Interrupt
  40. // in our helper thread. The various async methods have to cancel
  41. // any ongoing requests by calling request.Abort () at that point.
  42. // In a few places (UploadDataCore, UploadValuesCore,
  43. // UploadFileCore) we catch the ThreadInterruptedException and
  44. // abort the request there.
  45. //
  46. // Higher level routines (the async callbacks) also need to catch
  47. // the exception and raise the OnXXXXCompleted events there with
  48. // the "canceled" flag set to true.
  49. //
  50. // In a few other places where these helper routines are not used
  51. // (OpenReadAsync for example) catching the ThreadAbortException
  52. // also must abort the request.
  53. //
  54. // The Async methods currently differ in their implementation from
  55. // the .NET implementation in that we manually catch any other
  56. // exceptions and correctly raise the OnXXXXCompleted passing the
  57. // Exception that caused the problem. The .NET implementation
  58. // does not seem to have a mechanism to flag errors that happen
  59. // during downloads though. We do this because we still need to
  60. // catch the exception on these helper threads, or we would
  61. // otherwise kill the application (on the 2.x profile, uncaught
  62. // exceptions in threads terminate the application).
  63. //
  64. using System;
  65. using System.Collections.Specialized;
  66. using System.ComponentModel;
  67. using System.IO;
  68. using System.Runtime.InteropServices;
  69. using System.Runtime.Serialization;
  70. using System.Text;
  71. using System.Threading;
  72. using System.Net.Cache;
  73. #if NET_4_5
  74. using System.Threading.Tasks;
  75. #endif
  76. namespace System.Net
  77. {
  78. [ComVisible(true)]
  79. public class WebClient : Component
  80. {
  81. static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
  82. static byte [] hexBytes;
  83. ICredentials credentials;
  84. WebHeaderCollection headers;
  85. WebHeaderCollection responseHeaders;
  86. Uri baseAddress;
  87. string baseString;
  88. NameValueCollection queryString;
  89. bool is_busy;
  90. bool async;
  91. bool proxySet = false;
  92. Thread async_thread;
  93. Encoding encoding = Encoding.Default;
  94. IWebProxy proxy;
  95. // RequestCachePolicy cache_policy;
  96. #if NET_4_5
  97. CancellationTokenSource cts;
  98. #endif
  99. // Constructors
  100. static WebClient ()
  101. {
  102. hexBytes = new byte [16];
  103. int index = 0;
  104. for (int i = '0'; i <= '9'; i++, index++)
  105. hexBytes [index] = (byte) i;
  106. for (int i = 'a'; i <= 'f'; i++, index++)
  107. hexBytes [index] = (byte) i;
  108. }
  109. public WebClient ()
  110. {
  111. }
  112. // Properties
  113. public string BaseAddress {
  114. get {
  115. if (baseString == null) {
  116. if (baseAddress == null)
  117. return string.Empty;
  118. }
  119. baseString = baseAddress.ToString ();
  120. return baseString;
  121. }
  122. set {
  123. if (value == null || value.Length == 0) {
  124. baseAddress = null;
  125. } else {
  126. baseAddress = new Uri (value);
  127. }
  128. }
  129. }
  130. static Exception GetMustImplement ()
  131. {
  132. return new NotImplementedException ();
  133. }
  134. [MonoTODO ("Value can be set but is currently ignored")]
  135. public RequestCachePolicy CachePolicy
  136. {
  137. get {
  138. throw GetMustImplement ();
  139. }
  140. set { /*cache_policy = value;*/ }
  141. }
  142. [MonoTODO ("Value can be set but is ignored")]
  143. public bool UseDefaultCredentials
  144. {
  145. get {
  146. throw GetMustImplement ();
  147. }
  148. set {
  149. // This makes no sense in mono
  150. }
  151. }
  152. public ICredentials Credentials {
  153. get { return credentials; }
  154. set { credentials = value; }
  155. }
  156. public WebHeaderCollection Headers {
  157. get {
  158. if (headers == null)
  159. headers = new WebHeaderCollection ();
  160. return headers;
  161. }
  162. set { headers = value; }
  163. }
  164. public NameValueCollection QueryString {
  165. get {
  166. if (queryString == null)
  167. queryString = new NameValueCollection ();
  168. return queryString;
  169. }
  170. set { queryString = value; }
  171. }
  172. public WebHeaderCollection ResponseHeaders {
  173. get { return responseHeaders; }
  174. }
  175. public Encoding Encoding {
  176. get { return encoding; }
  177. set {
  178. if (value == null)
  179. throw new ArgumentNullException ("Encoding");
  180. encoding = value;
  181. }
  182. }
  183. public IWebProxy Proxy {
  184. get {
  185. if (!proxySet)
  186. return WebRequest.DefaultWebProxy;
  187. return proxy;
  188. }
  189. set {
  190. proxy = value;
  191. proxySet = true;
  192. }
  193. }
  194. public bool IsBusy {
  195. get {
  196. #if NET_4_5
  197. return is_busy || (cts != null);
  198. #else
  199. return is_busy;
  200. #endif
  201. }
  202. }
  203. // Methods
  204. void CheckBusy ()
  205. {
  206. if (IsBusy)
  207. throw new NotSupportedException ("WebClient does not support concurrent I/O operations.");
  208. }
  209. void SetBusy ()
  210. {
  211. lock (this) {
  212. CheckBusy ();
  213. is_busy = true;
  214. }
  215. }
  216. // DownloadData
  217. public byte [] DownloadData (string address)
  218. {
  219. if (address == null)
  220. throw new ArgumentNullException ("address");
  221. return DownloadData (CreateUri (address));
  222. }
  223. public byte [] DownloadData (Uri address)
  224. {
  225. if (address == null)
  226. throw new ArgumentNullException ("address");
  227. try {
  228. SetBusy ();
  229. async = false;
  230. return DownloadDataCore (address, null);
  231. } finally {
  232. is_busy = false;
  233. }
  234. }
  235. byte [] DownloadDataCore (Uri address, object userToken)
  236. {
  237. WebRequest request = null;
  238. try {
  239. request = SetupRequest (address);
  240. return ReadAll (request, userToken);
  241. } catch (ThreadInterruptedException){
  242. if (request != null)
  243. request.Abort ();
  244. throw new WebException ("User canceled the request", WebExceptionStatus.RequestCanceled);
  245. } catch (WebException) {
  246. throw;
  247. } catch (Exception ex) {
  248. throw new WebException ("An error occurred performing a WebClient request.", ex);
  249. }
  250. }
  251. // DownloadFile
  252. public void DownloadFile (string address, string fileName)
  253. {
  254. if (address == null)
  255. throw new ArgumentNullException ("address");
  256. DownloadFile (CreateUri (address), fileName);
  257. }
  258. public void DownloadFile (Uri address, string fileName)
  259. {
  260. if (address == null)
  261. throw new ArgumentNullException ("address");
  262. if (fileName == null)
  263. throw new ArgumentNullException ("fileName");
  264. try {
  265. SetBusy ();
  266. async = false;
  267. DownloadFileCore (address, fileName, null);
  268. } catch (WebException) {
  269. throw;
  270. } catch (Exception ex) {
  271. throw new WebException ("An error occurred " +
  272. "performing a WebClient request.", ex);
  273. } finally {
  274. is_busy = false;
  275. }
  276. }
  277. void DownloadFileCore (Uri address, string fileName, object userToken)
  278. {
  279. WebRequest request = null;
  280. using (FileStream f = new FileStream (fileName, FileMode.Create)) {
  281. try {
  282. request = SetupRequest (address);
  283. WebResponse response = GetWebResponse (request);
  284. Stream st = response.GetResponseStream ();
  285. int cLength = (int) response.ContentLength;
  286. int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
  287. byte [] buffer = new byte [length];
  288. int nread = 0;
  289. long notify_total = 0;
  290. while ((nread = st.Read (buffer, 0, length)) != 0){
  291. if (async){
  292. notify_total += nread;
  293. OnDownloadProgressChanged (
  294. new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, userToken));
  295. }
  296. f.Write (buffer, 0, nread);
  297. }
  298. } catch (ThreadInterruptedException){
  299. if (request != null)
  300. request.Abort ();
  301. throw;
  302. }
  303. }
  304. }
  305. // OpenRead
  306. public Stream OpenRead (string address)
  307. {
  308. if (address == null)
  309. throw new ArgumentNullException ("address");
  310. return OpenRead (CreateUri (address));
  311. }
  312. public Stream OpenRead (Uri address)
  313. {
  314. if (address == null)
  315. throw new ArgumentNullException ("address");
  316. WebRequest request = null;
  317. try {
  318. SetBusy ();
  319. async = false;
  320. request = SetupRequest (address);
  321. WebResponse response = GetWebResponse (request);
  322. return response.GetResponseStream ();
  323. } catch (WebException) {
  324. throw;
  325. } catch (Exception ex) {
  326. throw new WebException ("An error occurred " +
  327. "performing a WebClient request.", ex);
  328. } finally {
  329. is_busy = false;
  330. }
  331. }
  332. // OpenWrite
  333. public Stream OpenWrite (string address)
  334. {
  335. if (address == null)
  336. throw new ArgumentNullException ("address");
  337. return OpenWrite (CreateUri (address));
  338. }
  339. public Stream OpenWrite (string address, string method)
  340. {
  341. if (address == null)
  342. throw new ArgumentNullException ("address");
  343. return OpenWrite (CreateUri (address), method);
  344. }
  345. public Stream OpenWrite (Uri address)
  346. {
  347. return OpenWrite (address, (string) null);
  348. }
  349. public Stream OpenWrite (Uri address, string method)
  350. {
  351. if (address == null)
  352. throw new ArgumentNullException ("address");
  353. try {
  354. SetBusy ();
  355. async = false;
  356. WebRequest request = SetupRequest (address, method, true);
  357. return request.GetRequestStream ();
  358. } catch (WebException) {
  359. throw;
  360. } catch (Exception ex) {
  361. throw new WebException ("An error occurred " +
  362. "performing a WebClient request.", ex);
  363. } finally {
  364. is_busy = false;
  365. }
  366. }
  367. private string DetermineMethod (Uri address, string method, bool is_upload)
  368. {
  369. if (method != null)
  370. return method;
  371. if (address.Scheme == Uri.UriSchemeFtp)
  372. return (is_upload) ? "STOR" : "RETR";
  373. return (is_upload) ? "POST" : "GET";
  374. }
  375. // UploadData
  376. public byte [] UploadData (string address, byte [] data)
  377. {
  378. if (address == null)
  379. throw new ArgumentNullException ("address");
  380. return UploadData (CreateUri (address), data);
  381. }
  382. public byte [] UploadData (string address, string method, byte [] data)
  383. {
  384. if (address == null)
  385. throw new ArgumentNullException ("address");
  386. return UploadData (CreateUri (address), method, data);
  387. }
  388. public byte [] UploadData (Uri address, byte [] data)
  389. {
  390. return UploadData (address, (string) null, data);
  391. }
  392. public byte [] UploadData (Uri address, string method, byte [] data)
  393. {
  394. if (address == null)
  395. throw new ArgumentNullException ("address");
  396. if (data == null)
  397. throw new ArgumentNullException ("data");
  398. try {
  399. SetBusy ();
  400. async = false;
  401. return UploadDataCore (address, method, data, null);
  402. } catch (WebException) {
  403. throw;
  404. } catch (Exception ex) {
  405. throw new WebException ("An error occurred " +
  406. "performing a WebClient request.", ex);
  407. } finally {
  408. is_busy = false;
  409. }
  410. }
  411. byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
  412. {
  413. WebRequest request = SetupRequest (address, method, true);
  414. try {
  415. int contentLength = data.Length;
  416. request.ContentLength = contentLength;
  417. using (Stream stream = request.GetRequestStream ()) {
  418. stream.Write (data, 0, contentLength);
  419. }
  420. return ReadAll (request, userToken);
  421. } catch (ThreadInterruptedException){
  422. if (request != null)
  423. request.Abort ();
  424. throw;
  425. }
  426. }
  427. // UploadFile
  428. public byte [] UploadFile (string address, string fileName)
  429. {
  430. if (address == null)
  431. throw new ArgumentNullException ("address");
  432. return UploadFile (CreateUri (address), fileName);
  433. }
  434. public byte [] UploadFile (Uri address, string fileName)
  435. {
  436. return UploadFile (address, (string) null, fileName);
  437. }
  438. public byte [] UploadFile (string address, string method, string fileName)
  439. {
  440. return UploadFile (CreateUri (address), method, fileName);
  441. }
  442. public byte [] UploadFile (Uri address, string method, string fileName)
  443. {
  444. if (address == null)
  445. throw new ArgumentNullException ("address");
  446. if (fileName == null)
  447. throw new ArgumentNullException ("fileName");
  448. try {
  449. SetBusy ();
  450. async = false;
  451. return UploadFileCore (address, method, fileName, null);
  452. } catch (WebException) {
  453. throw;
  454. } catch (Exception ex) {
  455. throw new WebException ("An error occurred " +
  456. "performing a WebClient request.", ex);
  457. } finally {
  458. is_busy = false;
  459. }
  460. }
  461. byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
  462. {
  463. string fileCType = Headers ["Content-Type"];
  464. if (fileCType != null) {
  465. string lower = fileCType.ToLower ();
  466. if (lower.StartsWith ("multipart/"))
  467. throw new WebException ("Content-Type cannot be set to a multipart" +
  468. " type for this request.");
  469. } else {
  470. fileCType = "application/octet-stream";
  471. }
  472. bool needs_boundary = (method != "PUT"); // only verified case so far
  473. string boundary = null;
  474. if (needs_boundary) {
  475. boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
  476. Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
  477. }
  478. Stream reqStream = null;
  479. Stream fStream = null;
  480. byte [] resultBytes = null;
  481. fileName = Path.GetFullPath (fileName);
  482. WebRequest request = null;
  483. try {
  484. fStream = File.OpenRead (fileName);
  485. request = SetupRequest (address, method, true);
  486. reqStream = request.GetRequestStream ();
  487. byte [] bytes_boundary = null;
  488. if (needs_boundary) {
  489. bytes_boundary = Encoding.ASCII.GetBytes (boundary);
  490. reqStream.WriteByte ((byte) '-');
  491. reqStream.WriteByte ((byte) '-');
  492. reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
  493. reqStream.WriteByte ((byte) '\r');
  494. reqStream.WriteByte ((byte) '\n');
  495. string partHeaders = String.Format ("Content-Disposition: form-data; " +
  496. "name=\"file\"; filename=\"{0}\"\r\n" +
  497. "Content-Type: {1}\r\n\r\n",
  498. Path.GetFileName (fileName), fileCType);
  499. byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
  500. reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
  501. }
  502. int nread;
  503. long bytes_sent = 0;
  504. long file_size = -1;
  505. long step = 16384; // every 16kB
  506. if (fStream.CanSeek) {
  507. file_size = fStream.Length;
  508. step = file_size / 100;
  509. }
  510. var upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, 0, userToken);
  511. OnUploadProgressChanged (upload_args);
  512. byte [] buffer = new byte [4096];
  513. long sum = 0;
  514. while ((nread = fStream.Read (buffer, 0, 4096)) > 0) {
  515. reqStream.Write (buffer, 0, nread);
  516. bytes_sent += nread;
  517. sum += nread;
  518. if (sum >= step || nread < 4096) {
  519. int percent = 0;
  520. if (file_size > 0)
  521. percent = (int) (bytes_sent * 100 / file_size);
  522. upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, percent, userToken);
  523. OnUploadProgressChanged (upload_args);
  524. sum = 0;
  525. }
  526. }
  527. if (needs_boundary) {
  528. reqStream.WriteByte ((byte) '\r');
  529. reqStream.WriteByte ((byte) '\n');
  530. reqStream.WriteByte ((byte) '-');
  531. reqStream.WriteByte ((byte) '-');
  532. reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
  533. reqStream.WriteByte ((byte) '-');
  534. reqStream.WriteByte ((byte) '-');
  535. reqStream.WriteByte ((byte) '\r');
  536. reqStream.WriteByte ((byte) '\n');
  537. }
  538. reqStream.Close ();
  539. reqStream = null;
  540. resultBytes = ReadAll (request, userToken);
  541. } catch (ThreadInterruptedException){
  542. if (request != null)
  543. request.Abort ();
  544. throw;
  545. } finally {
  546. if (fStream != null)
  547. fStream.Close ();
  548. if (reqStream != null)
  549. reqStream.Close ();
  550. }
  551. return resultBytes;
  552. }
  553. public byte[] UploadValues (string address, NameValueCollection data)
  554. {
  555. if (address == null)
  556. throw new ArgumentNullException ("address");
  557. return UploadValues (CreateUri (address), data);
  558. }
  559. public byte[] UploadValues (string address, string method, NameValueCollection data)
  560. {
  561. if (address == null)
  562. throw new ArgumentNullException ("address");
  563. return UploadValues (CreateUri (address), method, data);
  564. }
  565. public byte[] UploadValues (Uri address, NameValueCollection data)
  566. {
  567. return UploadValues (address, (string) null, data);
  568. }
  569. public byte[] UploadValues (Uri address, string method, NameValueCollection data)
  570. {
  571. if (address == null)
  572. throw new ArgumentNullException ("address");
  573. if (data == null)
  574. throw new ArgumentNullException ("data");
  575. try {
  576. SetBusy ();
  577. async = false;
  578. return UploadValuesCore (address, method, data, null);
  579. } catch (WebException) {
  580. throw;
  581. } catch (Exception ex) {
  582. throw new WebException ("An error occurred " +
  583. "performing a WebClient request.", ex);
  584. } finally {
  585. is_busy = false;
  586. }
  587. }
  588. byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
  589. {
  590. string cType = Headers ["Content-Type"];
  591. if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
  592. throw new WebException ("Content-Type header cannot be changed from its default " +
  593. "value for this request.");
  594. Headers ["Content-Type"] = urlEncodedCType;
  595. WebRequest request = SetupRequest (uri, method, true);
  596. try {
  597. MemoryStream tmpStream = new MemoryStream ();
  598. foreach (string key in data) {
  599. byte [] bytes = Encoding.UTF8.GetBytes (key);
  600. UrlEncodeAndWrite (tmpStream, bytes);
  601. tmpStream.WriteByte ((byte) '=');
  602. bytes = Encoding.UTF8.GetBytes (data [key]);
  603. UrlEncodeAndWrite (tmpStream, bytes);
  604. tmpStream.WriteByte ((byte) '&');
  605. }
  606. int length = (int) tmpStream.Length;
  607. if (length > 0)
  608. tmpStream.SetLength (--length); // remove trailing '&'
  609. byte [] buf = tmpStream.GetBuffer ();
  610. request.ContentLength = length;
  611. using (Stream rqStream = request.GetRequestStream ()) {
  612. rqStream.Write (buf, 0, length);
  613. }
  614. tmpStream.Close ();
  615. return ReadAll (request, userToken);
  616. } catch (ThreadInterruptedException) {
  617. request.Abort ();
  618. throw;
  619. }
  620. }
  621. public string DownloadString (string address)
  622. {
  623. if (address == null)
  624. throw new ArgumentNullException ("address");
  625. return encoding.GetString (DownloadData (CreateUri (address)));
  626. }
  627. public string DownloadString (Uri address)
  628. {
  629. if (address == null)
  630. throw new ArgumentNullException ("address");
  631. return encoding.GetString (DownloadData (CreateUri (address)));
  632. }
  633. public string UploadString (string address, string data)
  634. {
  635. if (address == null)
  636. throw new ArgumentNullException ("address");
  637. if (data == null)
  638. throw new ArgumentNullException ("data");
  639. byte [] resp = UploadData (address, encoding.GetBytes (data));
  640. return encoding.GetString (resp);
  641. }
  642. public string UploadString (string address, string method, string data)
  643. {
  644. if (address == null)
  645. throw new ArgumentNullException ("address");
  646. if (data == null)
  647. throw new ArgumentNullException ("data");
  648. byte [] resp = UploadData (address, method, encoding.GetBytes (data));
  649. return encoding.GetString (resp);
  650. }
  651. public string UploadString (Uri address, string data)
  652. {
  653. if (address == null)
  654. throw new ArgumentNullException ("address");
  655. if (data == null)
  656. throw new ArgumentNullException ("data");
  657. byte [] resp = UploadData (address, encoding.GetBytes (data));
  658. return encoding.GetString (resp);
  659. }
  660. public string UploadString (Uri address, string method, string data)
  661. {
  662. if (address == null)
  663. throw new ArgumentNullException ("address");
  664. if (data == null)
  665. throw new ArgumentNullException ("data");
  666. byte [] resp = UploadData (address, method, encoding.GetBytes (data));
  667. return encoding.GetString (resp);
  668. }
  669. public event DownloadDataCompletedEventHandler DownloadDataCompleted;
  670. public event AsyncCompletedEventHandler DownloadFileCompleted;
  671. public event DownloadProgressChangedEventHandler DownloadProgressChanged;
  672. public event DownloadStringCompletedEventHandler DownloadStringCompleted;
  673. public event OpenReadCompletedEventHandler OpenReadCompleted;
  674. public event OpenWriteCompletedEventHandler OpenWriteCompleted;
  675. public event UploadDataCompletedEventHandler UploadDataCompleted;
  676. public event UploadFileCompletedEventHandler UploadFileCompleted;
  677. public event UploadProgressChangedEventHandler UploadProgressChanged;
  678. public event UploadStringCompletedEventHandler UploadStringCompleted;
  679. public event UploadValuesCompletedEventHandler UploadValuesCompleted;
  680. Uri CreateUri (string address)
  681. {
  682. Uri uri;
  683. try {
  684. if (baseAddress == null)
  685. uri = new Uri (address);
  686. else
  687. uri = new Uri (baseAddress, address);
  688. return CreateUri (uri);
  689. } catch {
  690. }
  691. return new Uri (Path.GetFullPath (address));
  692. }
  693. Uri CreateUri (Uri address)
  694. {
  695. Uri result = address;
  696. if (baseAddress != null && !result.IsAbsoluteUri) {
  697. try {
  698. result = new Uri (baseAddress, result.OriginalString);
  699. } catch {
  700. return result; // Not much we can do here.
  701. }
  702. }
  703. string query = result.Query;
  704. if (String.IsNullOrEmpty (query))
  705. query = GetQueryString (true);
  706. UriBuilder builder = new UriBuilder (address);
  707. if (!String.IsNullOrEmpty (query))
  708. builder.Query = query.Substring (1);
  709. return builder.Uri;
  710. }
  711. string GetQueryString (bool add_qmark)
  712. {
  713. if (queryString == null || queryString.Count == 0)
  714. return null;
  715. StringBuilder sb = new StringBuilder ();
  716. if (add_qmark)
  717. sb.Append ('?');
  718. foreach (string key in queryString)
  719. sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
  720. if (sb.Length != 0)
  721. sb.Length--; // removes last '&' or the '?' if empty.
  722. if (sb.Length == 0)
  723. return null;
  724. return sb.ToString ();
  725. }
  726. WebRequest SetupRequest (Uri uri)
  727. {
  728. WebRequest request = GetWebRequest (uri);
  729. if (proxySet)
  730. request.Proxy = Proxy;
  731. if (credentials != null)
  732. request.Credentials = credentials;
  733. else if (!String.IsNullOrEmpty (uri.UserInfo)) {
  734. // Perhaps this should be done by the underlying URI handler?
  735. ICredentials creds = GetCredentials (uri.UserInfo);
  736. if (creds != null)
  737. request.Credentials = creds;
  738. }
  739. // Special headers. These are properties of HttpWebRequest.
  740. // What do we do with other requests differnt from HttpWebRequest?
  741. if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
  742. HttpWebRequest req = (HttpWebRequest) request;
  743. string expect = headers ["Expect"];
  744. string contentType = headers ["Content-Type"];
  745. string accept = headers ["Accept"];
  746. string connection = headers ["Connection"];
  747. string userAgent = headers ["User-Agent"];
  748. string referer = headers ["Referer"];
  749. headers.RemoveInternal ("Expect");
  750. headers.RemoveInternal ("Content-Type");
  751. headers.RemoveInternal ("Accept");
  752. headers.RemoveInternal ("Connection");
  753. headers.RemoveInternal ("Referer");
  754. headers.RemoveInternal ("User-Agent");
  755. request.Headers = headers;
  756. if (expect != null && expect.Length > 0)
  757. req.Expect = expect;
  758. if (accept != null && accept.Length > 0)
  759. req.Accept = accept;
  760. if (contentType != null && contentType.Length > 0)
  761. req.ContentType = contentType;
  762. if (connection != null && connection.Length > 0)
  763. req.Connection = connection;
  764. if (userAgent != null && userAgent.Length > 0)
  765. req.UserAgent = userAgent;
  766. if (referer != null && referer.Length > 0)
  767. req.Referer = referer;
  768. }
  769. responseHeaders = null;
  770. return request;
  771. }
  772. WebRequest SetupRequest (Uri uri, string method, bool is_upload)
  773. {
  774. WebRequest request = SetupRequest (uri);
  775. request.Method = DetermineMethod (uri, method, is_upload);
  776. return request;
  777. }
  778. static NetworkCredential GetCredentials (string user_info)
  779. {
  780. string [] creds = user_info.Split (':');
  781. if (creds.Length != 2)
  782. return null;
  783. if (creds [0].IndexOf ('\\') != -1) {
  784. string [] user = creds [0].Split ('\\');
  785. if (user.Length != 2)
  786. return null;
  787. return new NetworkCredential (user [1], creds [1], user [0]);
  788. }
  789. return new NetworkCredential (creds [0], creds [1]);
  790. }
  791. byte [] ReadAll (WebRequest request, object userToken)
  792. {
  793. WebResponse response = GetWebResponse (request);
  794. Stream stream = response.GetResponseStream ();
  795. int length = (int) response.ContentLength;
  796. HttpWebRequest wreq = request as HttpWebRequest;
  797. if (length > -1 && wreq != null && (int) wreq.AutomaticDecompression != 0) {
  798. string content_encoding = ((HttpWebResponse) response).ContentEncoding;
  799. if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
  800. ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
  801. length = -1;
  802. }
  803. MemoryStream ms = null;
  804. bool nolength = (length == -1);
  805. int size = ((nolength) ? 8192 : length);
  806. if (nolength)
  807. ms = new MemoryStream ();
  808. long total = 0;
  809. int nread = 0;
  810. int offset = 0;
  811. byte [] buffer = new byte [size];
  812. while ((nread = stream.Read (buffer, offset, size)) != 0) {
  813. if (nolength) {
  814. ms.Write (buffer, 0, nread);
  815. } else {
  816. offset += nread;
  817. size -= nread;
  818. }
  819. if (async){
  820. total += nread;
  821. OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, userToken));
  822. }
  823. }
  824. if (nolength)
  825. return ms.ToArray ();
  826. return buffer;
  827. }
  828. string UrlEncode (string str)
  829. {
  830. StringBuilder result = new StringBuilder ();
  831. int len = str.Length;
  832. for (int i = 0; i < len; i++) {
  833. char c = str [i];
  834. if (c == ' ')
  835. result.Append ('+');
  836. else if ((c < '0' && c != '-' && c != '.') ||
  837. (c < 'A' && c > '9') ||
  838. (c > 'Z' && c < 'a' && c != '_') ||
  839. (c > 'z')) {
  840. result.Append ('%');
  841. int idx = ((int) c) >> 4;
  842. result.Append ((char) hexBytes [idx]);
  843. idx = ((int) c) & 0x0F;
  844. result.Append ((char) hexBytes [idx]);
  845. } else {
  846. result.Append (c);
  847. }
  848. }
  849. return result.ToString ();
  850. }
  851. static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
  852. {
  853. if (bytes == null)
  854. return;
  855. int len = bytes.Length;
  856. if (len == 0)
  857. return;
  858. for (int i = 0; i < len; i++) {
  859. char c = (char) bytes [i];
  860. if (c == ' ')
  861. stream.WriteByte ((byte) '+');
  862. else if ((c < '0' && c != '-' && c != '.') ||
  863. (c < 'A' && c > '9') ||
  864. (c > 'Z' && c < 'a' && c != '_') ||
  865. (c > 'z')) {
  866. stream.WriteByte ((byte) '%');
  867. int idx = ((int) c) >> 4;
  868. stream.WriteByte (hexBytes [idx]);
  869. idx = ((int) c) & 0x0F;
  870. stream.WriteByte (hexBytes [idx]);
  871. } else {
  872. stream.WriteByte ((byte) c);
  873. }
  874. }
  875. }
  876. public void CancelAsync ()
  877. {
  878. lock (this){
  879. #if NET_4_5
  880. if (cts != null) {
  881. cts.Cancel ();
  882. return;
  883. }
  884. #endif
  885. if (async_thread == null)
  886. return;
  887. //
  888. // We first flag things as done, in case the Interrupt hangs
  889. // or the thread decides to hang in some other way inside the
  890. // event handlers, or if we are stuck somewhere else. This
  891. // ensures that the WebClient object is reusable immediately
  892. //
  893. Thread t = async_thread;
  894. CompleteAsync ();
  895. t.Interrupt ();
  896. }
  897. }
  898. void CompleteAsync ()
  899. {
  900. lock (this) {
  901. is_busy = false;
  902. async_thread = null;
  903. #if NET_4_5
  904. if (cts != null)
  905. cts.Dispose ();
  906. cts = null;
  907. #endif
  908. }
  909. }
  910. // DownloadDataAsync
  911. public void DownloadDataAsync (Uri address)
  912. {
  913. DownloadDataAsync (address, null);
  914. }
  915. public void DownloadDataAsync (Uri address, object userToken)
  916. {
  917. if (address == null)
  918. throw new ArgumentNullException ("address");
  919. lock (this) {
  920. SetBusy ();
  921. async = true;
  922. async_thread = new Thread (delegate (object state) {
  923. object [] args = (object []) state;
  924. try {
  925. byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
  926. OnDownloadDataCompleted (
  927. new DownloadDataCompletedEventArgs (data, null, false, args [1]));
  928. } catch (Exception e){
  929. bool canceled = false;
  930. WebException we = e as WebException;
  931. if (we != null)
  932. canceled = we.Status == WebExceptionStatus.RequestCanceled;
  933. OnDownloadDataCompleted (
  934. new DownloadDataCompletedEventArgs (null, e, canceled, args [1]));
  935. }
  936. });
  937. object [] cb_args = new object [] { CreateUri (address), userToken };
  938. async_thread.IsBackground = true;
  939. async_thread.Start (cb_args);
  940. }
  941. }
  942. // DownloadFileAsync
  943. public void DownloadFileAsync (Uri address, string fileName)
  944. {
  945. DownloadFileAsync (address, fileName, null);
  946. }
  947. public void DownloadFileAsync (Uri address, string fileName, object userToken)
  948. {
  949. if (address == null)
  950. throw new ArgumentNullException ("address");
  951. if (fileName == null)
  952. throw new ArgumentNullException ("fileName");
  953. lock (this) {
  954. SetBusy ();
  955. async = true;
  956. async_thread = new Thread (delegate (object state) {
  957. object [] args = (object []) state;
  958. try {
  959. DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
  960. OnDownloadFileCompleted (
  961. new AsyncCompletedEventArgs (null, false, args [2]));
  962. } catch (ThreadInterruptedException){
  963. OnDownloadFileCompleted (
  964. new AsyncCompletedEventArgs (null, true, args [2]));
  965. } catch (Exception e){
  966. OnDownloadFileCompleted (
  967. new AsyncCompletedEventArgs (e, false, args [2]));
  968. }});
  969. object [] cb_args = new object [] { CreateUri (address), fileName, userToken };
  970. async_thread.IsBackground = true;
  971. async_thread.Start (cb_args);
  972. }
  973. }
  974. // DownloadStringAsync
  975. public void DownloadStringAsync (Uri address)
  976. {
  977. DownloadStringAsync (address, null);
  978. }
  979. public void DownloadStringAsync (Uri address, object userToken)
  980. {
  981. if (address == null)
  982. throw new ArgumentNullException ("address");
  983. lock (this) {
  984. SetBusy ();
  985. async = true;
  986. async_thread = new Thread (delegate (object state) {
  987. object [] args = (object []) state;
  988. try {
  989. string data = encoding.GetString (DownloadDataCore ((Uri) args [0], args [1]));
  990. OnDownloadStringCompleted (
  991. new DownloadStringCompletedEventArgs (data, null, false, args [1]));
  992. } catch (Exception e){
  993. bool canceled = false;
  994. WebException we = e as WebException;
  995. if (we != null)
  996. canceled = we.Status == WebExceptionStatus.RequestCanceled;
  997. OnDownloadStringCompleted (
  998. new DownloadStringCompletedEventArgs (null, e, canceled, args [1]));
  999. }});
  1000. object [] cb_args = new object [] { CreateUri (address), userToken };
  1001. async_thread.IsBackground = true;
  1002. async_thread.Start (cb_args);
  1003. }
  1004. }
  1005. // OpenReadAsync
  1006. public void OpenReadAsync (Uri address)
  1007. {
  1008. OpenReadAsync (address, null);
  1009. }
  1010. public void OpenReadAsync (Uri address, object userToken)
  1011. {
  1012. if (address == null)
  1013. throw new ArgumentNullException ("address");
  1014. lock (this) {
  1015. SetBusy ();
  1016. async = true;
  1017. async_thread = new Thread (delegate (object state) {
  1018. object [] args = (object []) state;
  1019. WebRequest request = null;
  1020. try {
  1021. request = SetupRequest ((Uri) args [0]);
  1022. WebResponse response = GetWebResponse (request);
  1023. Stream stream = response.GetResponseStream ();
  1024. OnOpenReadCompleted (
  1025. new OpenReadCompletedEventArgs (stream, null, false, args [1]));
  1026. } catch (ThreadInterruptedException){
  1027. if (request != null)
  1028. request.Abort ();
  1029. OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, args [1]));
  1030. } catch (Exception e){
  1031. OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, e, false, args [1]));
  1032. } });
  1033. object [] cb_args = new object [] { CreateUri (address), userToken };
  1034. async_thread.IsBackground = true;
  1035. async_thread.Start (cb_args);
  1036. }
  1037. }
  1038. // OpenWriteAsync
  1039. public void OpenWriteAsync (Uri address)
  1040. {
  1041. OpenWriteAsync (address, null);
  1042. }
  1043. public void OpenWriteAsync (Uri address, string method)
  1044. {
  1045. OpenWriteAsync (address, method, null);
  1046. }
  1047. public void OpenWriteAsync (Uri address, string method, object userToken)
  1048. {
  1049. if (address == null)
  1050. throw new ArgumentNullException ("address");
  1051. lock (this) {
  1052. SetBusy ();
  1053. async = true;
  1054. async_thread = new Thread (delegate (object state) {
  1055. object [] args = (object []) state;
  1056. WebRequest request = null;
  1057. try {
  1058. request = SetupRequest ((Uri) args [0], (string) args [1], true);
  1059. Stream stream = request.GetRequestStream ();
  1060. OnOpenWriteCompleted (
  1061. new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
  1062. } catch (ThreadInterruptedException){
  1063. if (request != null)
  1064. request.Abort ();
  1065. OnOpenWriteCompleted (
  1066. new OpenWriteCompletedEventArgs (null, null, true, args [2]));
  1067. } catch (Exception e){
  1068. OnOpenWriteCompleted (
  1069. new OpenWriteCompletedEventArgs (null, e, false, args [2]));
  1070. }});
  1071. object [] cb_args = new object [] { CreateUri (address), method, userToken };
  1072. async_thread.IsBackground = true;
  1073. async_thread.Start (cb_args);
  1074. }
  1075. }
  1076. // UploadDataAsync
  1077. public void UploadDataAsync (Uri address, byte [] data)
  1078. {
  1079. UploadDataAsync (address, null, data);
  1080. }
  1081. public void UploadDataAsync (Uri address, string method, byte [] data)
  1082. {
  1083. UploadDataAsync (address, method, data, null);
  1084. }
  1085. public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
  1086. {
  1087. if (address == null)
  1088. throw new ArgumentNullException ("address");
  1089. if (data == null)
  1090. throw new ArgumentNullException ("data");
  1091. lock (this) {
  1092. SetBusy ();
  1093. async = true;
  1094. async_thread = new Thread (delegate (object state) {
  1095. object [] args = (object []) state;
  1096. byte [] data2;
  1097. try {
  1098. data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
  1099. OnUploadDataCompleted (
  1100. new UploadDataCompletedEventArgs (data2, null, false, args [3]));
  1101. } catch (ThreadInterruptedException){
  1102. OnUploadDataCompleted (
  1103. new UploadDataCompletedEventArgs (null, null, true, args [3]));
  1104. } catch (Exception e){
  1105. OnUploadDataCompleted (
  1106. new UploadDataCompletedEventArgs (null, e, false, args [3]));
  1107. }});
  1108. object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
  1109. async_thread.IsBackground = true;
  1110. async_thread.Start (cb_args);
  1111. }
  1112. }
  1113. // UploadFileAsync
  1114. public void UploadFileAsync (Uri address, string fileName)
  1115. {
  1116. UploadFileAsync (address, null, fileName);
  1117. }
  1118. public void UploadFileAsync (Uri address, string method, string fileName)
  1119. {
  1120. UploadFileAsync (address, method, fileName, null);
  1121. }
  1122. public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
  1123. {
  1124. if (address == null)
  1125. throw new ArgumentNullException ("address");
  1126. if (fileName == null)
  1127. throw new ArgumentNullException ("fileName");
  1128. lock (this) {
  1129. SetBusy ();
  1130. async = true;
  1131. async_thread = new Thread (delegate (object state) {
  1132. object [] args = (object []) state;
  1133. byte [] data;
  1134. try {
  1135. data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
  1136. OnUploadFileCompleted (
  1137. new UploadFileCompletedEventArgs (data, null, false, args [3]));
  1138. } catch (ThreadInterruptedException){
  1139. OnUploadFileCompleted (
  1140. new UploadFileCompletedEventArgs (null, null, true, args [3]));
  1141. } catch (Exception e){
  1142. OnUploadFileCompleted (
  1143. new UploadFileCompletedEventArgs (null, e, false, args [3]));
  1144. }});
  1145. object [] cb_args = new object [] { CreateUri (address), method, fileName, userToken };
  1146. async_thread.IsBackground = true;
  1147. async_thread.Start (cb_args);
  1148. }
  1149. }
  1150. // UploadStringAsync
  1151. public void UploadStringAsync (Uri address, string data)
  1152. {
  1153. UploadStringAsync (address, null, data);
  1154. }
  1155. public void UploadStringAsync (Uri address, string method, string data)
  1156. {
  1157. UploadStringAsync (address, method, data, null);
  1158. }
  1159. public void UploadStringAsync (Uri address, string method, string data, object userToken)
  1160. {
  1161. if (address == null)
  1162. throw new ArgumentNullException ("address");
  1163. if (data == null)
  1164. throw new ArgumentNullException ("data");
  1165. lock (this) {
  1166. CheckBusy ();
  1167. async = true;
  1168. async_thread = new Thread (delegate (object state) {
  1169. object [] args = (object []) state;
  1170. try {
  1171. string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
  1172. OnUploadStringCompleted (
  1173. new UploadStringCompletedEventArgs (data2, null, false, args [3]));
  1174. } catch (ThreadInterruptedException){
  1175. OnUploadStringCompleted (
  1176. new UploadStringCompletedEventArgs (null, null, true, args [3]));
  1177. } catch (Exception e){
  1178. OnUploadStringCompleted (
  1179. new UploadStringCompletedEventArgs (null, e, false, args [3]));
  1180. }});
  1181. object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
  1182. async_thread.IsBackground = true;
  1183. async_thread.Start (cb_args);
  1184. }
  1185. }
  1186. // UploadValuesAsync
  1187. public void UploadValuesAsync (Uri address, NameValueCollection data)
  1188. {
  1189. UploadValuesAsync (address, null, data);
  1190. }
  1191. public void UploadValuesAsync (Uri address, string method, NameValueCollection data)
  1192. {
  1193. UploadValuesAsync (address, method, data, null);
  1194. }
  1195. public void UploadValuesAsync (Uri address, string method, NameValueCollection data, object userToken)
  1196. {
  1197. if (address == null)
  1198. throw new ArgumentNullException ("address");
  1199. if (data == null)
  1200. throw new ArgumentNullException ("data");
  1201. lock (this) {
  1202. CheckBusy ();
  1203. async = true;
  1204. async_thread = new Thread (delegate (object state) {
  1205. object [] args = (object []) state;
  1206. try {
  1207. byte [] values = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
  1208. OnUploadValuesCompleted (
  1209. new UploadValuesCompletedEventArgs (values, null, false, args [3]));
  1210. } catch (ThreadInterruptedException){
  1211. OnUploadValuesCompleted (
  1212. new UploadValuesCompletedEventArgs (null, null, true, args [3]));
  1213. } catch (Exception e){
  1214. OnUploadValuesCompleted (
  1215. new UploadValuesCompletedEventArgs (null, e, false, args [3]));
  1216. }});
  1217. object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
  1218. async_thread.IsBackground = true;
  1219. async_thread.Start (cb_args);
  1220. }
  1221. }
  1222. protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs e)
  1223. {
  1224. CompleteAsync ();
  1225. if (DownloadDataCompleted != null)
  1226. DownloadDataCompleted (this, e);
  1227. }
  1228. protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs e)
  1229. {
  1230. CompleteAsync ();
  1231. if (DownloadFileCompleted != null)
  1232. DownloadFileCompleted (this, e);
  1233. }
  1234. protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
  1235. {
  1236. if (DownloadProgressChanged != null)
  1237. DownloadProgressChanged (this, e);
  1238. }
  1239. protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs e)
  1240. {
  1241. CompleteAsync ();
  1242. if (DownloadStringCompleted != null)
  1243. DownloadStringCompleted (this, e);
  1244. }
  1245. protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs e)
  1246. {
  1247. CompleteAsync ();
  1248. if (OpenReadCompleted != null)
  1249. OpenReadCompleted (this, e);
  1250. }
  1251. protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs e)
  1252. {
  1253. CompleteAsync ();
  1254. if (OpenWriteCompleted != null)
  1255. OpenWriteCompleted (this, e);
  1256. }
  1257. protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs e)
  1258. {
  1259. CompleteAsync ();
  1260. if (UploadDataCompleted != null)
  1261. UploadDataCompleted (this, e);
  1262. }
  1263. protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs e)
  1264. {
  1265. CompleteAsync ();
  1266. if (UploadFileCompleted != null)
  1267. UploadFileCompleted (this, e);
  1268. }
  1269. protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
  1270. {
  1271. if (UploadProgressChanged != null)
  1272. UploadProgressChanged (this, e);
  1273. }
  1274. protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs e)
  1275. {
  1276. CompleteAsync ();
  1277. if (UploadStringCompleted != null)
  1278. UploadStringCompleted (this, e);
  1279. }
  1280. protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs e)
  1281. {
  1282. CompleteAsync ();
  1283. if (UploadValuesCompleted != null)
  1284. UploadValuesCompleted (this, e);
  1285. }
  1286. protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
  1287. {
  1288. WebResponse response = request.EndGetResponse (result);
  1289. responseHeaders = response.Headers;
  1290. return response;
  1291. }
  1292. protected virtual WebRequest GetWebRequest (Uri address)
  1293. {
  1294. return WebRequest.Create (address);
  1295. }
  1296. protected virtual WebResponse GetWebResponse (WebRequest request)
  1297. {
  1298. WebResponse response = request.GetResponse ();
  1299. responseHeaders = response.Headers;
  1300. return response;
  1301. }
  1302. #if NET_4_5
  1303. // DownloadDataTaskAsync
  1304. public Task<byte[]> DownloadDataTaskAsync (string address)
  1305. {
  1306. return DownloadDataTaskAsync (CreateUri (address));
  1307. }
  1308. public async Task<byte[]> DownloadDataTaskAsync (Uri address)
  1309. {
  1310. WebRequest request = null;
  1311. WebResponse response = null;
  1312. try {
  1313. SetBusy ();
  1314. cts = new CancellationTokenSource ();
  1315. request = await SetupRequestAsync (address);
  1316. response = await GetWebResponseTaskAsync (request, cts.Token);
  1317. var result = await ReadAllTaskAsync (request, response, cts.Token);
  1318. // Has to run on original context
  1319. OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (result, null, false, null));
  1320. return result;
  1321. } catch (WebException ex) {
  1322. OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, false, null));
  1323. throw;
  1324. } catch (OperationCanceledException) {
  1325. if (request != null)
  1326. request.Abort ();
  1327. OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, null, true, null));
  1328. throw;
  1329. } catch (Exception ex) {
  1330. OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, true, null));
  1331. throw new WebException ("An error occurred performing a WebClient request.", ex);
  1332. } finally {
  1333. if (response != null)
  1334. response.Close ();
  1335. }
  1336. }
  1337. Task<WebRequest> SetupRequestAsync (Uri address)
  1338. {
  1339. return Task.Factory.StartNew (() => SetupRequest (address));
  1340. }
  1341. async Task<WebRequest> SetupRequestAsync (Uri address, string method, bool is_upload)
  1342. {
  1343. WebRequest request = await SetupRequestAsync (address).ConfigureAwait (false);
  1344. request.Method = DetermineMethod (address, method, is_upload);
  1345. return request;
  1346. }
  1347. async Task<WebResponse> GetWebResponseTaskAsync (WebRequest request, CancellationToken token)
  1348. {
  1349. token.ThrowIfCancellationRequested ();
  1350. WebResponse response = await request.GetResponseAsync ().ConfigureAwait (false);
  1351. token.ThrowIfCancellationRequested ();
  1352. responseHeaders = response.Headers;
  1353. return response;
  1354. }
  1355. async Task<byte[]> ReadAllTaskAsync (WebRequest request, WebResponse response, CancellationToken token)
  1356. {
  1357. Stream stream = response.GetResponseStream ();
  1358. int length = (int)response.ContentLength;
  1359. HttpWebRequest wreq = request as HttpWebRequest;
  1360. if (length > -1 && wreq != null && (int)wreq.AutomaticDecompression != 0) {
  1361. string content_encoding = ((HttpWebResponse)response).ContentEncoding;
  1362. if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
  1363. ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
  1364. length = -1;
  1365. }
  1366. MemoryStream ms = null;
  1367. bool nolength = (length == -1);
  1368. int size = ((nolength) ? 8192 : length);
  1369. if (nolength)
  1370. ms = new MemoryStream ();
  1371. long total = 0;
  1372. int nread = 0;
  1373. int offset = 0;
  1374. byte [] buffer = new byte [size];
  1375. token.ThrowIfCancellationRequested ();
  1376. while ((nread = await stream.ReadAsync (buffer, offset, size, token)) != 0) {
  1377. if (nolength) {
  1378. ms.Write (buffer, 0, nread);
  1379. } else {
  1380. offset += nread;
  1381. size -= nread;
  1382. }
  1383. total += nread;
  1384. OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, null));
  1385. token.ThrowIfCancellationRequested ();
  1386. }
  1387. return nolength ? ms.ToArray () : buffer;
  1388. }
  1389. // DownloadFileTaskAsync
  1390. public Task DownloadFileTaskAsync (string address, string fileName)
  1391. {
  1392. if (address == null)
  1393. throw new ArgumentNullException ("address");
  1394. return DownloadFileTaskAsync (CreateUri (address), fileName);
  1395. }
  1396. public async Task DownloadFileTaskAsync (Uri address, string fileName)
  1397. {
  1398. if (address == null)
  1399. throw new ArgumentNullException ("address");
  1400. if (fileName == null)
  1401. throw new ArgumentNullException ("fileName");
  1402. WebRequest request = null;
  1403. WebResponse response = null;
  1404. try {
  1405. SetBusy ();
  1406. cts = new CancellationTokenSource ();
  1407. request = await SetupRequestAsync (address);
  1408. response = await GetWebResponseTaskAsync (request, cts.Token);
  1409. await DownloadFileTaskAsyncCore (request, response, fileName, cts.Token);
  1410. OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, false, null));
  1411. } catch (WebException ex) {
  1412. OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
  1413. throw;
  1414. } catch (OperationCanceledException) {
  1415. if (request != null)
  1416. request.Abort ();
  1417. OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, true, null));
  1418. throw;
  1419. } catch (Exception ex) {
  1420. OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
  1421. throw new WebException ("An error occurred " +
  1422. "performing a WebClient request.", ex);
  1423. } finally {
  1424. if (response != null)
  1425. response.Close ();
  1426. }
  1427. }
  1428. async Task DownloadFileTaskAsyncCore (WebRequest request, WebResponse response,
  1429. string fileName, CancellationToken token)
  1430. {
  1431. using (FileStream f = new FileStream (fileName, FileMode.Create)) {
  1432. Stream st = response.GetResponseStream ();
  1433. int cLength = (int)response.ContentLength;
  1434. int length = (cLength <= -1 || cLength > 32 * 1024) ? 32 * 1024 : cLength;
  1435. byte [] buffer = new byte [length];
  1436. int nread = 0;
  1437. long notify_total = 0;
  1438. token.ThrowIfCancellationRequested ();
  1439. while ((nread = await st.ReadAsync (buffer, 0, length, token)) != 0) {
  1440. notify_total += nread;
  1441. OnDownloadProgressChanged (
  1442. new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, null));
  1443. token.ThrowIfCancellationRequested ();
  1444. await f.WriteAsync (buffer, 0, nread, token);
  1445. token.ThrowIfCancellationRequested ();
  1446. }
  1447. }
  1448. }
  1449. // OpenReadTaskAsync
  1450. public Task<Stream> OpenReadTaskAsync (string address)
  1451. {
  1452. if (address == null)
  1453. throw new ArgumentNullException ("address");
  1454. return OpenReadTaskAsync (CreateUri (address));
  1455. }
  1456. public async Task<Stream> OpenReadTaskAsync (Uri address)
  1457. {
  1458. if (address == null)
  1459. throw new ArgumentNullException ("address");
  1460. WebRequest request = null;
  1461. try {
  1462. SetBusy ();
  1463. cts = new CancellationTokenSource ();
  1464. request = await SetupRequestAsync (address);
  1465. WebResponse response = await GetWebResponseTaskAsync (request, cts.Token);
  1466. var result = response.GetResponseStream ();
  1467. cts.Token.ThrowIfCancellationRequested ();
  1468. OnOpenReadCompleted (new OpenReadCompletedEventArgs (result, null, false, null));
  1469. return result;
  1470. } catch (WebException ex) {
  1471. OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
  1472. throw;
  1473. } catch (OperationCanceledException) {
  1474. if (request != null)
  1475. request.Abort ();
  1476. OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, null));
  1477. throw;
  1478. } catch (Exception ex) {
  1479. OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
  1480. throw new WebException ("An error occurred " +
  1481. "performing a WebClient request.", ex);
  1482. }
  1483. }
  1484. // DownloadStringTaskAsync
  1485. public Task<string> DownloadStringTaskAsync (string address)
  1486. {
  1487. if (address == null)
  1488. throw new ArgumentNullException ("address");
  1489. return DownloadStringTaskAsync (CreateUri (address));
  1490. }
  1491. public async Task<string> DownloadStringTaskAsync (Uri address)
  1492. {
  1493. if (address == null)
  1494. throw new ArgumentNullException ("address");
  1495. WebRequest request = null;
  1496. WebResponse response = null;
  1497. try {
  1498. SetBusy ();
  1499. cts = new CancellationTokenSource ();
  1500. request = await SetupRequestAsync (address);
  1501. response = await GetWebResponseTaskAsync (request

Large files files are truncated, but you can click here to view the full file