2 // System.Net.WebClient
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)
11 // Copyright 2003 Ximian, Inc. (http://www.ximian.com)
12 // Copyright 2006, 2010 Novell, Inc. (http://www.novell.com)
13 // Copyright 2012 Xamarin Inc. (http://www.xamarin.com)
16 // Permission is hereby granted, free of charge, to any person obtaining
17 // a copy of this software and associated documentation files (the
18 // "Software"), to deal in the Software without restriction, including
19 // without limitation the rights to use, copy, modify, merge, publish,
20 // distribute, sublicense, and/or sell copies of the Software, and to
21 // permit persons to whom the Software is furnished to do so, subject to
22 // the following conditions:
24 // The above copyright notice and this permission notice shall be
25 // included in all copies or substantial portions of the Software.
27 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
28 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
29 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
30 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
31 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
32 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
33 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
36 // Notes on CancelAsync and Async methods:
38 // WebClient.CancelAsync is implemented by calling Thread.Interrupt
39 // in our helper thread. The various async methods have to cancel
40 // any ongoing requests by calling request.Abort () at that point.
41 // In a few places (UploadDataCore, UploadValuesCore,
42 // UploadFileCore) we catch the ThreadInterruptedException and
43 // abort the request there.
45 // Higher level routines (the async callbacks) also need to catch
46 // the exception and raise the OnXXXXCompleted events there with
47 // the "canceled" flag set to true.
49 // In a few other places where these helper routines are not used
50 // (OpenReadAsync for example) catching the ThreadAbortException
51 // also must abort the request.
53 // The Async methods currently differ in their implementation from
54 // the .NET implementation in that we manually catch any other
55 // exceptions and correctly raise the OnXXXXCompleted passing the
56 // Exception that caused the problem. The .NET implementation
57 // does not seem to have a mechanism to flag errors that happen
58 // during downloads though. We do this because we still need to
59 // catch the exception on these helper threads, or we would
60 // otherwise kill the application (on the 2.x profile, uncaught
61 // exceptions in threads terminate the application).
64 using System.Collections.Specialized;
65 using System.ComponentModel;
67 using System.Runtime.InteropServices;
68 using System.Runtime.Serialization;
70 using System.Threading;
71 using System.Net.Cache;
73 using System.Threading.Tasks;
79 public class WebClient : Component
81 static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
82 static byte [] hexBytes;
83 ICredentials credentials;
84 WebHeaderCollection headers;
85 WebHeaderCollection responseHeaders;
88 NameValueCollection queryString;
91 bool proxySet = false;
93 Encoding encoding = Encoding.Default;
95 // RequestCachePolicy cache_policy;
97 CancellationTokenSource cts;
103 hexBytes = new byte [16];
105 for (int i = '0'; i <= '9'; i++, index++)
106 hexBytes [index] = (byte) i;
108 for (int i = 'a'; i <= 'f'; i++, index++)
109 hexBytes [index] = (byte) i;
118 public string BaseAddress {
120 if (baseString == null) {
121 if (baseAddress == null)
125 baseString = baseAddress.ToString ();
130 if (value == null || value.Length == 0) {
133 baseAddress = new Uri (value);
138 static Exception GetMustImplement ()
140 return new NotImplementedException ();
143 [MonoTODO ("Value can be set but is currently ignored")]
144 public RequestCachePolicy CachePolicy
147 throw GetMustImplement ();
149 set { /*cache_policy = value;*/ }
152 [MonoTODO ("Value can be set but is ignored")]
153 public bool UseDefaultCredentials
156 throw GetMustImplement ();
159 // This makes no sense in mono
163 public ICredentials Credentials {
164 get { return credentials; }
165 set { credentials = value; }
168 public WebHeaderCollection Headers {
171 headers = new WebHeaderCollection ();
175 set { headers = value; }
178 public NameValueCollection QueryString {
180 if (queryString == null)
181 queryString = new NameValueCollection ();
185 set { queryString = value; }
188 public WebHeaderCollection ResponseHeaders {
189 get { return responseHeaders; }
192 public Encoding Encoding {
193 get { return encoding; }
196 throw new ArgumentNullException ("Encoding");
201 public IWebProxy Proxy {
204 return WebRequest.DefaultWebProxy;
217 return is_busy || (cts != null);
228 throw new NotSupportedException ("WebClient does not support concurrent I/O operations.");
241 public byte [] DownloadData (string address)
244 throw new ArgumentNullException ("address");
246 return DownloadData (CreateUri (address));
249 public byte [] DownloadData (Uri address)
252 throw new ArgumentNullException ("address");
257 return DownloadDataCore (address, null);
263 byte [] DownloadDataCore (Uri address, object userToken)
265 WebRequest request = null;
268 request = SetupRequest (address);
269 return ReadAll (request, userToken);
270 } catch (ThreadInterruptedException){
273 throw new WebException ("User canceled the request", WebExceptionStatus.RequestCanceled);
274 } catch (WebException) {
276 } catch (Exception ex) {
277 throw new WebException ("An error occurred performing a WebClient request.", ex);
283 public void DownloadFile (string address, string fileName)
286 throw new ArgumentNullException ("address");
288 DownloadFile (CreateUri (address), fileName);
291 public void DownloadFile (Uri address, string fileName)
294 throw new ArgumentNullException ("address");
295 if (fileName == null)
296 throw new ArgumentNullException ("fileName");
301 DownloadFileCore (address, fileName, null);
302 } catch (WebException) {
304 } catch (Exception ex) {
305 throw new WebException ("An error occurred " +
306 "performing a WebClient request.", ex);
312 void DownloadFileCore (Uri address, string fileName, object userToken)
314 WebRequest request = null;
316 using (FileStream f = new FileStream (fileName, FileMode.Create)) {
318 request = SetupRequest (address);
319 WebResponse response = GetWebResponse (request);
320 Stream st = response.GetResponseStream ();
322 int cLength = (int) response.ContentLength;
323 int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
324 byte [] buffer = new byte [length];
327 long notify_total = 0;
328 while ((nread = st.Read (buffer, 0, length)) != 0){
330 notify_total += nread;
331 OnDownloadProgressChanged (
332 new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, userToken));
335 f.Write (buffer, 0, nread);
337 } catch (ThreadInterruptedException){
347 public Stream OpenRead (string address)
350 throw new ArgumentNullException ("address");
351 return OpenRead (CreateUri (address));
354 public Stream OpenRead (Uri address)
357 throw new ArgumentNullException ("address");
359 WebRequest request = null;
363 request = SetupRequest (address);
364 WebResponse response = GetWebResponse (request);
365 return response.GetResponseStream ();
366 } catch (WebException) {
368 } catch (Exception ex) {
369 throw new WebException ("An error occurred " +
370 "performing a WebClient request.", ex);
378 public Stream OpenWrite (string address)
381 throw new ArgumentNullException ("address");
383 return OpenWrite (CreateUri (address));
386 public Stream OpenWrite (string address, string method)
389 throw new ArgumentNullException ("address");
391 return OpenWrite (CreateUri (address), method);
394 public Stream OpenWrite (Uri address)
396 return OpenWrite (address, (string) null);
399 public Stream OpenWrite (Uri address, string method)
402 throw new ArgumentNullException ("address");
407 WebRequest request = SetupRequest (address, method, true);
408 return request.GetRequestStream ();
409 } catch (WebException) {
411 } catch (Exception ex) {
412 throw new WebException ("An error occurred " +
413 "performing a WebClient request.", ex);
419 private string DetermineMethod (Uri address, string method, bool is_upload)
424 if (address.Scheme == Uri.UriSchemeFtp)
425 return (is_upload) ? "STOR" : "RETR";
427 return (is_upload) ? "POST" : "GET";
432 public byte [] UploadData (string address, byte [] data)
435 throw new ArgumentNullException ("address");
437 return UploadData (CreateUri (address), data);
440 public byte [] UploadData (string address, string method, byte [] data)
443 throw new ArgumentNullException ("address");
445 return UploadData (CreateUri (address), method, data);
448 public byte [] UploadData (Uri address, byte [] data)
450 return UploadData (address, (string) null, data);
453 public byte [] UploadData (Uri address, string method, byte [] data)
456 throw new ArgumentNullException ("address");
458 throw new ArgumentNullException ("data");
463 return UploadDataCore (address, method, data, null);
464 } catch (WebException) {
466 } catch (Exception ex) {
467 throw new WebException ("An error occurred " +
468 "performing a WebClient request.", ex);
474 byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
476 WebRequest request = SetupRequest (address, method, true);
478 int contentLength = data.Length;
479 request.ContentLength = contentLength;
480 using (Stream stream = request.GetRequestStream ()) {
481 stream.Write (data, 0, contentLength);
484 return ReadAll (request, userToken);
485 } catch (ThreadInterruptedException){
494 public byte [] UploadFile (string address, string fileName)
497 throw new ArgumentNullException ("address");
499 return UploadFile (CreateUri (address), fileName);
502 public byte [] UploadFile (Uri address, string fileName)
504 return UploadFile (address, (string) null, fileName);
507 public byte [] UploadFile (string address, string method, string fileName)
509 return UploadFile (CreateUri (address), method, fileName);
512 public byte [] UploadFile (Uri address, string method, string fileName)
515 throw new ArgumentNullException ("address");
516 if (fileName == null)
517 throw new ArgumentNullException ("fileName");
522 return UploadFileCore (address, method, fileName, null);
523 } catch (WebException) {
525 } catch (Exception ex) {
526 throw new WebException ("An error occurred " +
527 "performing a WebClient request.", ex);
533 byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
535 string fileCType = Headers ["Content-Type"];
536 if (fileCType != null) {
537 string lower = fileCType.ToLower ();
538 if (lower.StartsWith ("multipart/"))
539 throw new WebException ("Content-Type cannot be set to a multipart" +
540 " type for this request.");
542 fileCType = "application/octet-stream";
545 bool needs_boundary = (method != "PUT"); // only verified case so far
546 string boundary = null;
547 if (needs_boundary) {
548 boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
549 Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
551 Stream reqStream = null;
552 Stream fStream = null;
553 byte [] resultBytes = null;
555 fileName = Path.GetFullPath (fileName);
557 WebRequest request = null;
559 fStream = File.OpenRead (fileName);
560 request = SetupRequest (address, method, true);
561 reqStream = request.GetRequestStream ();
562 byte [] bytes_boundary = null;
563 if (needs_boundary) {
564 bytes_boundary = Encoding.ASCII.GetBytes (boundary);
565 reqStream.WriteByte ((byte) '-');
566 reqStream.WriteByte ((byte) '-');
567 reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
568 reqStream.WriteByte ((byte) '\r');
569 reqStream.WriteByte ((byte) '\n');
570 string partHeaders = String.Format ("Content-Disposition: form-data; " +
571 "name=\"file\"; filename=\"{0}\"\r\n" +
572 "Content-Type: {1}\r\n\r\n",
573 Path.GetFileName (fileName), fileCType);
575 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
576 reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
581 long step = 16384; // every 16kB
582 if (fStream.CanSeek) {
583 file_size = fStream.Length;
584 step = file_size / 100;
586 var upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, 0, userToken);
587 OnUploadProgressChanged (upload_args);
588 byte [] buffer = new byte [4096];
590 while ((nread = fStream.Read (buffer, 0, 4096)) > 0) {
591 reqStream.Write (buffer, 0, nread);
594 if (sum >= step || nread < 4096) {
597 percent = (int) (bytes_sent * 100 / file_size);
598 upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, percent, userToken);
599 OnUploadProgressChanged (upload_args);
604 if (needs_boundary) {
605 reqStream.WriteByte ((byte) '\r');
606 reqStream.WriteByte ((byte) '\n');
607 reqStream.WriteByte ((byte) '-');
608 reqStream.WriteByte ((byte) '-');
609 reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
610 reqStream.WriteByte ((byte) '-');
611 reqStream.WriteByte ((byte) '-');
612 reqStream.WriteByte ((byte) '\r');
613 reqStream.WriteByte ((byte) '\n');
617 resultBytes = ReadAll (request, userToken);
618 } catch (ThreadInterruptedException){
626 if (reqStream != null)
633 public byte[] UploadValues (string address, NameValueCollection data)
636 throw new ArgumentNullException ("address");
638 return UploadValues (CreateUri (address), data);
641 public byte[] UploadValues (string address, string method, NameValueCollection data)
644 throw new ArgumentNullException ("address");
645 return UploadValues (CreateUri (address), method, data);
648 public byte[] UploadValues (Uri address, NameValueCollection data)
650 return UploadValues (address, (string) null, data);
653 public byte[] UploadValues (Uri address, string method, NameValueCollection data)
656 throw new ArgumentNullException ("address");
658 throw new ArgumentNullException ("data");
663 return UploadValuesCore (address, method, data, null);
664 } catch (WebException) {
666 } catch (Exception ex) {
667 throw new WebException ("An error occurred " +
668 "performing a WebClient request.", ex);
674 byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
676 string cType = Headers ["Content-Type"];
677 if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
678 throw new WebException ("Content-Type header cannot be changed from its default " +
679 "value for this request.");
681 Headers ["Content-Type"] = urlEncodedCType;
682 WebRequest request = SetupRequest (uri, method, true);
684 MemoryStream tmpStream = new MemoryStream ();
685 foreach (string key in data) {
686 byte [] bytes = Encoding.UTF8.GetBytes (key);
687 UrlEncodeAndWrite (tmpStream, bytes);
688 tmpStream.WriteByte ((byte) '=');
689 bytes = Encoding.UTF8.GetBytes (data [key]);
690 UrlEncodeAndWrite (tmpStream, bytes);
691 tmpStream.WriteByte ((byte) '&');
694 int length = (int) tmpStream.Length;
696 tmpStream.SetLength (--length); // remove trailing '&'
698 byte [] buf = tmpStream.GetBuffer ();
699 request.ContentLength = length;
700 using (Stream rqStream = request.GetRequestStream ()) {
701 rqStream.Write (buf, 0, length);
705 return ReadAll (request, userToken);
706 } catch (ThreadInterruptedException) {
712 public string DownloadString (string address)
715 throw new ArgumentNullException ("address");
717 return encoding.GetString (DownloadData (CreateUri (address)));
720 public string DownloadString (Uri address)
723 throw new ArgumentNullException ("address");
725 return encoding.GetString (DownloadData (CreateUri (address)));
728 public string UploadString (string address, string data)
731 throw new ArgumentNullException ("address");
733 throw new ArgumentNullException ("data");
735 byte [] resp = UploadData (address, encoding.GetBytes (data));
736 return encoding.GetString (resp);
739 public string UploadString (string address, string method, string data)
742 throw new ArgumentNullException ("address");
744 throw new ArgumentNullException ("data");
746 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
747 return encoding.GetString (resp);
750 public string UploadString (Uri address, string data)
753 throw new ArgumentNullException ("address");
755 throw new ArgumentNullException ("data");
757 byte [] resp = UploadData (address, encoding.GetBytes (data));
758 return encoding.GetString (resp);
761 public string UploadString (Uri address, string method, string data)
764 throw new ArgumentNullException ("address");
766 throw new ArgumentNullException ("data");
768 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
769 return encoding.GetString (resp);
772 public event DownloadDataCompletedEventHandler DownloadDataCompleted;
773 public event AsyncCompletedEventHandler DownloadFileCompleted;
774 public event DownloadProgressChangedEventHandler DownloadProgressChanged;
775 public event DownloadStringCompletedEventHandler DownloadStringCompleted;
776 public event OpenReadCompletedEventHandler OpenReadCompleted;
777 public event OpenWriteCompletedEventHandler OpenWriteCompleted;
778 public event UploadDataCompletedEventHandler UploadDataCompleted;
779 public event UploadFileCompletedEventHandler UploadFileCompleted;
780 public event UploadProgressChangedEventHandler UploadProgressChanged;
781 public event UploadStringCompletedEventHandler UploadStringCompleted;
782 public event UploadValuesCompletedEventHandler UploadValuesCompleted;
784 Uri CreateUri (string address)
788 if (baseAddress == null)
789 uri = new Uri (address);
791 uri = new Uri (baseAddress, address);
792 return CreateUri (uri);
795 return new Uri (Path.GetFullPath (address));
798 Uri CreateUri (Uri address)
800 Uri result = address;
801 if (baseAddress != null && !result.IsAbsoluteUri) {
803 result = new Uri (baseAddress, result.OriginalString);
805 return result; // Not much we can do here.
809 string query = result.Query;
810 if (String.IsNullOrEmpty (query))
811 query = GetQueryString (true);
812 UriBuilder builder = new UriBuilder (address);
813 if (!String.IsNullOrEmpty (query))
814 builder.Query = query.Substring (1);
818 string GetQueryString (bool add_qmark)
820 if (queryString == null || queryString.Count == 0)
823 StringBuilder sb = new StringBuilder ();
827 foreach (string key in queryString)
828 sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
831 sb.Length--; // removes last '&' or the '?' if empty.
836 return sb.ToString ();
839 WebRequest SetupRequest (Uri uri)
841 WebRequest request = GetWebRequest (uri);
843 request.Proxy = Proxy;
844 if (credentials != null)
845 request.Credentials = credentials;
846 else if (!String.IsNullOrEmpty (uri.UserInfo)) {
847 // Perhaps this should be done by the underlying URI handler?
848 ICredentials creds = GetCredentials (uri.UserInfo);
850 request.Credentials = creds;
853 // Special headers. These are properties of HttpWebRequest.
854 // What do we do with other requests differnt from HttpWebRequest?
855 if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
856 HttpWebRequest req = (HttpWebRequest) request;
857 string expect = headers ["Expect"];
858 string contentType = headers ["Content-Type"];
859 string accept = headers ["Accept"];
860 string connection = headers ["Connection"];
861 string userAgent = headers ["User-Agent"];
862 string referer = headers ["Referer"];
863 headers.RemoveInternal ("Expect");
864 headers.RemoveInternal ("Content-Type");
865 headers.RemoveInternal ("Accept");
866 headers.RemoveInternal ("Connection");
867 headers.RemoveInternal ("Referer");
868 headers.RemoveInternal ("User-Agent");
869 request.Headers = headers;
871 if (expect != null && expect.Length > 0)
874 if (accept != null && accept.Length > 0)
877 if (contentType != null && contentType.Length > 0)
878 req.ContentType = contentType;
880 if (connection != null && connection.Length > 0)
881 req.Connection = connection;
883 if (userAgent != null && userAgent.Length > 0)
884 req.UserAgent = userAgent;
886 if (referer != null && referer.Length > 0)
887 req.Referer = referer;
890 responseHeaders = null;
894 WebRequest SetupRequest (Uri uri, string method, bool is_upload)
896 WebRequest request = SetupRequest (uri);
897 request.Method = DetermineMethod (uri, method, is_upload);
901 static NetworkCredential GetCredentials (string user_info)
903 string [] creds = user_info.Split (':');
904 if (creds.Length != 2)
907 if (creds [0].IndexOf ('\\') != -1) {
908 string [] user = creds [0].Split ('\\');
909 if (user.Length != 2)
911 return new NetworkCredential (user [1], creds [1], user [0]);
913 return new NetworkCredential (creds [0], creds [1]);
916 byte [] ReadAll (WebRequest request, object userToken)
918 WebResponse response = GetWebResponse (request);
919 Stream stream = response.GetResponseStream ();
920 int length = (int) response.ContentLength;
921 HttpWebRequest wreq = request as HttpWebRequest;
923 if (length > -1 && wreq != null && (int) wreq.AutomaticDecompression != 0) {
924 string content_encoding = ((HttpWebResponse) response).ContentEncoding;
925 if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
926 ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
930 MemoryStream ms = null;
931 bool nolength = (length == -1);
932 int size = ((nolength) ? 8192 : length);
934 ms = new MemoryStream ();
939 byte [] buffer = new byte [size];
940 while ((nread = stream.Read (buffer, offset, size)) != 0) {
942 ms.Write (buffer, 0, nread);
949 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, userToken));
954 return ms.ToArray ();
959 string UrlEncode (string str)
961 StringBuilder result = new StringBuilder ();
963 int len = str.Length;
964 for (int i = 0; i < len; i++) {
968 else if ((c < '0' && c != '-' && c != '.') ||
969 (c < 'A' && c > '9') ||
970 (c > 'Z' && c < 'a' && c != '_') ||
973 int idx = ((int) c) >> 4;
974 result.Append ((char) hexBytes [idx]);
975 idx = ((int) c) & 0x0F;
976 result.Append ((char) hexBytes [idx]);
982 return result.ToString ();
985 static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
990 int len = bytes.Length;
994 for (int i = 0; i < len; i++) {
995 char c = (char) bytes [i];
997 stream.WriteByte ((byte) '+');
998 else if ((c < '0' && c != '-' && c != '.') ||
999 (c < 'A' && c > '9') ||
1000 (c > 'Z' && c < 'a' && c != '_') ||
1002 stream.WriteByte ((byte) '%');
1003 int idx = ((int) c) >> 4;
1004 stream.WriteByte (hexBytes [idx]);
1005 idx = ((int) c) & 0x0F;
1006 stream.WriteByte (hexBytes [idx]);
1008 stream.WriteByte ((byte) c);
1013 public void CancelAsync ()
1023 if (async_thread == null)
1027 // We first flag things as done, in case the Interrupt hangs
1028 // or the thread decides to hang in some other way inside the
1029 // event handlers, or if we are stuck somewhere else. This
1030 // ensures that the WebClient object is reusable immediately
1032 Thread t = async_thread;
1038 void CompleteAsync ()
1042 async_thread = null;
1051 // DownloadDataAsync
1053 public void DownloadDataAsync (Uri address)
1055 DownloadDataAsync (address, null);
1058 public void DownloadDataAsync (Uri address, object userToken)
1060 if (address == null)
1061 throw new ArgumentNullException ("address");
1067 async_thread = new Thread (delegate (object state) {
1068 object [] args = (object []) state;
1070 byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
1071 OnDownloadDataCompleted (
1072 new DownloadDataCompletedEventArgs (data, null, false, args [1]));
1073 } catch (Exception e){
1074 bool canceled = false;
1075 WebException we = e as WebException;
1077 canceled = we.Status == WebExceptionStatus.RequestCanceled;
1078 OnDownloadDataCompleted (
1079 new DownloadDataCompletedEventArgs (null, e, canceled, args [1]));
1082 object [] cb_args = new object [] {address, userToken};
1083 async_thread.Start (cb_args);
1087 // DownloadFileAsync
1089 public void DownloadFileAsync (Uri address, string fileName)
1091 DownloadFileAsync (address, fileName, null);
1094 public void DownloadFileAsync (Uri address, string fileName, object userToken)
1096 if (address == null)
1097 throw new ArgumentNullException ("address");
1098 if (fileName == null)
1099 throw new ArgumentNullException ("fileName");
1105 async_thread = new Thread (delegate (object state) {
1106 object [] args = (object []) state;
1108 DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
1109 OnDownloadFileCompleted (
1110 new AsyncCompletedEventArgs (null, false, args [2]));
1111 } catch (ThreadInterruptedException){
1112 OnDownloadFileCompleted (
1113 new AsyncCompletedEventArgs (null, true, args [2]));
1114 } catch (Exception e){
1115 OnDownloadFileCompleted (
1116 new AsyncCompletedEventArgs (e, false, args [2]));
1118 object [] cb_args = new object [] {address, fileName, userToken};
1119 async_thread.Start (cb_args);
1123 // DownloadStringAsync
1125 public void DownloadStringAsync (Uri address)
1127 DownloadStringAsync (address, null);
1130 public void DownloadStringAsync (Uri address, object userToken)
1132 if (address == null)
1133 throw new ArgumentNullException ("address");
1139 async_thread = new Thread (delegate (object state) {
1140 object [] args = (object []) state;
1142 string data = encoding.GetString (DownloadDataCore ((Uri) args [0], args [1]));
1143 OnDownloadStringCompleted (
1144 new DownloadStringCompletedEventArgs (data, null, false, args [1]));
1145 } catch (Exception e){
1146 bool canceled = false;
1147 WebException we = e as WebException;
1149 canceled = we.Status == WebExceptionStatus.RequestCanceled;
1150 OnDownloadStringCompleted (
1151 new DownloadStringCompletedEventArgs (null, e, canceled, args [1]));
1153 object [] cb_args = new object [] {address, userToken};
1154 async_thread.Start (cb_args);
1160 public void OpenReadAsync (Uri address)
1162 OpenReadAsync (address, null);
1165 public void OpenReadAsync (Uri address, object userToken)
1167 if (address == null)
1168 throw new ArgumentNullException ("address");
1174 async_thread = new Thread (delegate (object state) {
1175 object [] args = (object []) state;
1176 WebRequest request = null;
1178 request = SetupRequest ((Uri) args [0]);
1179 WebResponse response = GetWebResponse (request);
1180 Stream stream = response.GetResponseStream ();
1181 OnOpenReadCompleted (
1182 new OpenReadCompletedEventArgs (stream, null, false, args [1]));
1183 } catch (ThreadInterruptedException){
1184 if (request != null)
1187 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, args [1]));
1188 } catch (Exception e){
1189 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, e, false, args [1]));
1191 object [] cb_args = new object [] {address, userToken};
1192 async_thread.Start (cb_args);
1198 public void OpenWriteAsync (Uri address)
1200 OpenWriteAsync (address, null);
1203 public void OpenWriteAsync (Uri address, string method)
1205 OpenWriteAsync (address, method, null);
1208 public void OpenWriteAsync (Uri address, string method, object userToken)
1210 if (address == null)
1211 throw new ArgumentNullException ("address");
1217 async_thread = new Thread (delegate (object state) {
1218 object [] args = (object []) state;
1219 WebRequest request = null;
1221 request = SetupRequest ((Uri) args [0], (string) args [1], true);
1222 Stream stream = request.GetRequestStream ();
1223 OnOpenWriteCompleted (
1224 new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
1225 } catch (ThreadInterruptedException){
1226 if (request != null)
1228 OnOpenWriteCompleted (
1229 new OpenWriteCompletedEventArgs (null, null, true, args [2]));
1230 } catch (Exception e){
1231 OnOpenWriteCompleted (
1232 new OpenWriteCompletedEventArgs (null, e, false, args [2]));
1234 object [] cb_args = new object [] {address, method, userToken};
1235 async_thread.Start (cb_args);
1241 public void UploadDataAsync (Uri address, byte [] data)
1243 UploadDataAsync (address, null, data);
1246 public void UploadDataAsync (Uri address, string method, byte [] data)
1248 UploadDataAsync (address, method, data, null);
1251 public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
1253 if (address == null)
1254 throw new ArgumentNullException ("address");
1256 throw new ArgumentNullException ("data");
1262 async_thread = new Thread (delegate (object state) {
1263 object [] args = (object []) state;
1267 data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
1269 OnUploadDataCompleted (
1270 new UploadDataCompletedEventArgs (data2, null, false, args [3]));
1271 } catch (ThreadInterruptedException){
1272 OnUploadDataCompleted (
1273 new UploadDataCompletedEventArgs (null, null, true, args [3]));
1274 } catch (Exception e){
1275 OnUploadDataCompleted (
1276 new UploadDataCompletedEventArgs (null, e, false, args [3]));
1278 object [] cb_args = new object [] {address, method, data, userToken};
1279 async_thread.Start (cb_args);
1285 public void UploadFileAsync (Uri address, string fileName)
1287 UploadFileAsync (address, null, fileName);
1290 public void UploadFileAsync (Uri address, string method, string fileName)
1292 UploadFileAsync (address, method, fileName, null);
1295 public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
1297 if (address == null)
1298 throw new ArgumentNullException ("address");
1299 if (fileName == null)
1300 throw new ArgumentNullException ("fileName");
1306 async_thread = new Thread (delegate (object state) {
1307 object [] args = (object []) state;
1311 data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
1312 OnUploadFileCompleted (
1313 new UploadFileCompletedEventArgs (data, null, false, args [3]));
1314 } catch (ThreadInterruptedException){
1315 OnUploadFileCompleted (
1316 new UploadFileCompletedEventArgs (null, null, true, args [3]));
1317 } catch (Exception e){
1318 OnUploadFileCompleted (
1319 new UploadFileCompletedEventArgs (null, e, false, args [3]));
1321 object [] cb_args = new object [] {address, method, fileName, userToken};
1322 async_thread.Start (cb_args);
1326 // UploadStringAsync
1328 public void UploadStringAsync (Uri address, string data)
1330 UploadStringAsync (address, null, data);
1333 public void UploadStringAsync (Uri address, string method, string data)
1335 UploadStringAsync (address, method, data, null);
1338 public void UploadStringAsync (Uri address, string method, string data, object userToken)
1340 if (address == null)
1341 throw new ArgumentNullException ("address");
1343 throw new ArgumentNullException ("data");
1349 async_thread = new Thread (delegate (object state) {
1350 object [] args = (object []) state;
1353 string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
1354 OnUploadStringCompleted (
1355 new UploadStringCompletedEventArgs (data2, null, false, args [3]));
1356 } catch (ThreadInterruptedException){
1357 OnUploadStringCompleted (
1358 new UploadStringCompletedEventArgs (null, null, true, args [3]));
1359 } catch (Exception e){
1360 OnUploadStringCompleted (
1361 new UploadStringCompletedEventArgs (null, e, false, args [3]));
1363 object [] cb_args = new object [] {address, method, data, userToken};
1364 async_thread.Start (cb_args);
1368 // UploadValuesAsync
1370 public void UploadValuesAsync (Uri address, NameValueCollection data)
1372 UploadValuesAsync (address, null, data);
1375 public void UploadValuesAsync (Uri address, string method, NameValueCollection data)
1377 UploadValuesAsync (address, method, data, null);
1380 public void UploadValuesAsync (Uri address, string method, NameValueCollection data, object userToken)
1382 if (address == null)
1383 throw new ArgumentNullException ("address");
1385 throw new ArgumentNullException ("data");
1391 async_thread = new Thread (delegate (object state) {
1392 object [] args = (object []) state;
1394 byte [] values = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
1395 OnUploadValuesCompleted (
1396 new UploadValuesCompletedEventArgs (values, null, false, args [3]));
1397 } catch (ThreadInterruptedException){
1398 OnUploadValuesCompleted (
1399 new UploadValuesCompletedEventArgs (null, null, true, args [3]));
1400 } catch (Exception e){
1401 OnUploadValuesCompleted (
1402 new UploadValuesCompletedEventArgs (null, e, false, args [3]));
1404 object [] cb_args = new object [] {address, method, data, userToken};
1405 async_thread.Start (cb_args);
1409 protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs e)
1412 if (DownloadDataCompleted != null)
1413 DownloadDataCompleted (this, e);
1416 protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs e)
1419 if (DownloadFileCompleted != null)
1420 DownloadFileCompleted (this, e);
1423 protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
1425 if (DownloadProgressChanged != null)
1426 DownloadProgressChanged (this, e);
1429 protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs e)
1432 if (DownloadStringCompleted != null)
1433 DownloadStringCompleted (this, e);
1436 protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs e)
1439 if (OpenReadCompleted != null)
1440 OpenReadCompleted (this, e);
1443 protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs e)
1446 if (OpenWriteCompleted != null)
1447 OpenWriteCompleted (this, e);
1450 protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs e)
1453 if (UploadDataCompleted != null)
1454 UploadDataCompleted (this, e);
1457 protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs e)
1460 if (UploadFileCompleted != null)
1461 UploadFileCompleted (this, e);
1464 protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
1466 if (UploadProgressChanged != null)
1467 UploadProgressChanged (this, e);
1470 protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs e)
1473 if (UploadStringCompleted != null)
1474 UploadStringCompleted (this, e);
1477 protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs e)
1480 if (UploadValuesCompleted != null)
1481 UploadValuesCompleted (this, e);
1484 protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
1486 WebResponse response = request.EndGetResponse (result);
1487 responseHeaders = response.Headers;
1491 protected virtual WebRequest GetWebRequest (Uri address)
1493 return WebRequest.Create (address);
1496 protected virtual WebResponse GetWebResponse (WebRequest request)
1498 WebResponse response = request.GetResponse ();
1499 responseHeaders = response.Headers;
1505 // DownloadDataTaskAsync
1507 public Task<byte[]> DownloadDataTaskAsync (string address)
1509 return DownloadDataTaskAsync (CreateUri (address));
1512 public async Task<byte[]> DownloadDataTaskAsync (Uri address)
1514 WebRequest request = null;
1515 WebResponse response = null;
1518 cts = new CancellationTokenSource ();
1519 request = await SetupRequestAsync (address);
1520 response = await GetWebResponseTaskAsync (request, cts.Token);
1521 var result = await ReadAllTaskAsync (request, response, cts.Token);
1522 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (result, null, false, null));
1524 } catch (WebException ex) {
1525 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, false, null));
1527 } catch (OperationCanceledException) {
1528 if (request != null)
1530 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, null, true, null));
1532 } catch (Exception ex) {
1533 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, true, null));
1534 throw new WebException ("An error occurred performing a WebClient request.", ex);
1536 if (response != null)
1541 Task<WebRequest> SetupRequestAsync (Uri address)
1543 return Task.Factory.StartNew (() => SetupRequest (address));
1546 async Task<WebRequest> SetupRequestAsync (Uri address, string method, bool is_upload)
1548 WebRequest request = await SetupRequestAsync (address);
1549 request.Method = DetermineMethod (address, method, is_upload);
1553 async Task<WebResponse> GetWebResponseTaskAsync (WebRequest request, CancellationToken token)
1555 token.ThrowIfCancellationRequested ();
1556 WebResponse response = await request.GetResponseAsync ();
1557 token.ThrowIfCancellationRequested ();
1558 responseHeaders = response.Headers;
1562 async Task<byte[]> ReadAllTaskAsync (WebRequest request, WebResponse response, CancellationToken token)
1564 Stream stream = response.GetResponseStream ();
1565 int length = (int)response.ContentLength;
1566 HttpWebRequest wreq = request as HttpWebRequest;
1568 if (length > -1 && wreq != null && (int)wreq.AutomaticDecompression != 0) {
1569 string content_encoding = ((HttpWebResponse)response).ContentEncoding;
1570 if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
1571 ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
1575 MemoryStream ms = null;
1576 bool nolength = (length == -1);
1577 int size = ((nolength) ? 8192 : length);
1579 ms = new MemoryStream ();
1584 byte [] buffer = new byte [size];
1585 token.ThrowIfCancellationRequested ();
1586 while ((nread = await stream.ReadAsync (buffer, offset, size, token)) != 0) {
1588 ms.Write (buffer, 0, nread);
1594 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, null));
1595 token.ThrowIfCancellationRequested ();
1598 return nolength ? ms.ToArray () : buffer;
1601 // DownloadFileTaskAsync
1603 public Task DownloadFileTaskAsync (string address, string fileName)
1605 if (address == null)
1606 throw new ArgumentNullException ("address");
1608 return DownloadFileTaskAsync (CreateUri (address), fileName);
1611 public async Task DownloadFileTaskAsync (Uri address, string fileName)
1613 if (address == null)
1614 throw new ArgumentNullException ("address");
1615 if (fileName == null)
1616 throw new ArgumentNullException ("fileName");
1618 WebRequest request = null;
1619 WebResponse response = null;
1623 cts = new CancellationTokenSource ();
1624 request = await SetupRequestAsync (address);
1625 response = await GetWebResponseTaskAsync (request, cts.Token);
1626 await DownloadFileTaskAsyncCore (request, response, fileName, cts.Token);
1627 OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, false, null));
1628 } catch (WebException ex) {
1629 OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
1631 } catch (OperationCanceledException) {
1632 if (request != null)
1634 OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, true, null));
1636 } catch (Exception ex) {
1637 OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
1638 throw new WebException ("An error occurred " +
1639 "performing a WebClient request.", ex);
1641 if (response != null)
1646 async Task DownloadFileTaskAsyncCore (WebRequest request, WebResponse response,
1647 string fileName, CancellationToken token)
1649 using (FileStream f = new FileStream (fileName, FileMode.Create)) {
1650 Stream st = response.GetResponseStream ();
1652 int cLength = (int)response.ContentLength;
1653 int length = (cLength <= -1 || cLength > 32 * 1024) ? 32 * 1024 : cLength;
1654 byte [] buffer = new byte [length];
1657 long notify_total = 0;
1658 token.ThrowIfCancellationRequested ();
1659 while ((nread = await st.ReadAsync (buffer, 0, length, token)) != 0) {
1660 notify_total += nread;
1661 OnDownloadProgressChanged (
1662 new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, null));
1663 token.ThrowIfCancellationRequested ();
1664 await f.WriteAsync (buffer, 0, nread, token);
1665 token.ThrowIfCancellationRequested ();
1670 // OpenReadTaskAsync
1672 public Task<Stream> OpenReadTaskAsync (string address)
1674 if (address == null)
1675 throw new ArgumentNullException ("address");
1676 return OpenReadTaskAsync (CreateUri (address));
1679 public async Task<Stream> OpenReadTaskAsync (Uri address)
1681 if (address == null)
1682 throw new ArgumentNullException ("address");
1684 WebRequest request = null;
1687 cts = new CancellationTokenSource ();
1688 request = await SetupRequestAsync (address);
1689 WebResponse response = await GetWebResponseTaskAsync (request, cts.Token);
1690 var result = response.GetResponseStream ();
1691 cts.Token.ThrowIfCancellationRequested ();
1692 OnOpenReadCompleted (new OpenReadCompletedEventArgs (result, null, false, null));
1694 } catch (WebException ex) {
1695 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
1697 } catch (OperationCanceledException) {
1698 if (request != null)
1700 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, null));
1702 } catch (Exception ex) {
1703 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
1704 throw new WebException ("An error occurred " +
1705 "performing a WebClient request.", ex);
1709 // DownloadStringTaskAsync
1711 public Task<string> DownloadStringTaskAsync (string address)
1713 if (address == null)
1714 throw new ArgumentNullException ("address");
1716 return DownloadStringTaskAsync (CreateUri (address));
1719 public async Task<string> DownloadStringTaskAsync (Uri address)
1721 if (address == null)
1722 throw new ArgumentNullException ("address");
1724 WebRequest request = null;
1725 WebResponse response = null;
1729 cts = new CancellationTokenSource ();
1730 request = await SetupRequestAsync (address);
1731 response = await GetWebResponseTaskAsync (request, cts.Token);
1732 var data = await ReadAllTaskAsync (request, response, cts.Token);
1733 cts.Token.ThrowIfCancellationRequested ();
1734 var text = encoding.GetString (data);
1735 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (text, null, false, null));
1737 } catch (WebException ex) {
1738 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, ex, false, null));
1740 } catch (OperationCanceledException) {
1741 if (request != null)
1743 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, null, true, null));
1745 } catch (Exception ex) {
1746 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, ex, true, null));
1747 throw new WebException ("An error occurred performing a WebClient request.", ex);
1749 if (response != null)
1754 // OpenWriteTaskAsync
1756 public Task<Stream> OpenWriteTaskAsync (string address)
1758 if (address == null)
1759 throw new ArgumentNullException ("address");
1761 return OpenWriteTaskAsync (CreateUri (address));
1764 public Task<Stream> OpenWriteTaskAsync (string address, string method)
1766 if (address == null)
1767 throw new ArgumentNullException ("address");
1769 return OpenWriteTaskAsync (CreateUri (address), method);
1772 public Task<Stream> OpenWriteTaskAsync (Uri address)
1774 return OpenWriteTaskAsync (address, (string) null);
1777 public async Task<Stream> OpenWriteTaskAsync (Uri address, string method)
1779 if (address == null)
1780 throw new ArgumentNullException ("address");
1782 WebRequest request = null;
1785 cts = new CancellationTokenSource ();
1786 request = SetupRequest (address);
1787 return await request.GetRequestStreamAsync ();
1788 } catch (WebException) {
1790 } catch (OperationCanceledException) {
1791 if (request != null)
1794 } catch (Exception ex) {
1795 throw new WebException ("An error occurred " +
1796 "performing a WebClient request.", ex);
1802 // UploadDataTaskAsync
1804 public Task<byte[]> UploadDataTaskAsync (string address, byte [] data)
1806 if (address == null)
1807 throw new ArgumentNullException ("address");
1809 return UploadDataTaskAsync (CreateUri (address), data);
1812 public Task<byte[]> UploadDataTaskAsync (string address, string method, byte [] data)
1814 if (address == null)
1815 throw new ArgumentNullException ("address");
1817 return UploadDataTaskAsync (CreateUri (address), method, data);
1820 public Task<byte[]> UploadDataTaskAsync (Uri address, byte [] data)
1822 return UploadDataTaskAsync (address, (string) null, data);
1825 public async Task<byte[]> UploadDataTaskAsync (Uri address, string method, byte [] data)
1827 if (address == null)
1828 throw new ArgumentNullException ("address");
1830 throw new ArgumentNullException ("data");
1832 WebRequest request = null;
1835 cts = new CancellationTokenSource ();
1836 request = await SetupRequestAsync (address, method, true);
1837 var result = await UploadDataTaskAsyncCore (request, data, cts.Token);
1838 OnUploadDataCompleted (new UploadDataCompletedEventArgs (result, null, false, null));
1840 } catch (WebException ex) {
1841 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, ex, false, null));
1843 } catch (OperationCanceledException) {
1844 if (request != null)
1846 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, null, true, null));
1848 } catch (Exception ex) {
1849 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, ex, true, null));
1850 throw new WebException ("An error occurred performing a WebClient request.", ex);
1854 async Task<byte[]> UploadDataTaskAsyncCore (WebRequest request, byte[] data, CancellationToken token)
1856 token.ThrowIfCancellationRequested ();
1858 int contentLength = data.Length;
1859 request.ContentLength = contentLength;
1860 using (Stream stream = await request.GetRequestStreamAsync ()) {
1861 token.ThrowIfCancellationRequested ();
1862 await stream.WriteAsync (data, 0, contentLength, token);
1863 token.ThrowIfCancellationRequested ();
1866 WebResponse response = null;
1869 response = await GetWebResponseTaskAsync (request, token);
1870 return await ReadAllTaskAsync (request, response, token);
1872 if (response != null)
1877 // UploadFileTaskAsync
1879 public Task<byte[]> UploadFileTaskAsync (string address, string fileName)
1881 if (address == null)
1882 throw new ArgumentNullException ("address");
1884 return UploadFileTaskAsync (CreateUri (address), fileName);
1887 public Task<byte[]> UploadFileTaskAsync (Uri address, string fileName)
1889 return UploadFileTaskAsync (address, (string) null, fileName);
1892 public Task<byte[]> UploadFileTaskAsync (string address, string method, string fileName)
1894 return UploadFileTaskAsync (CreateUri (address), method, fileName);
1897 public async Task<byte[]> UploadFileTaskAsync (Uri address, string method, string fileName)
1899 if (address == null)
1900 throw new ArgumentNullException ("address");
1901 if (fileName == null)
1902 throw new ArgumentNullException ("fileName");
1904 WebRequest request = null;
1907 cts = new CancellationTokenSource ();
1908 request = await SetupRequestAsync (address, method, true);
1909 var result = await UploadFileTaskAsyncCore (request, method, fileName, cts.Token);
1910 OnUploadFileCompleted (new UploadFileCompletedEventArgs (result, null, false, null));
1912 } catch (WebException ex) {
1913 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, false, null));
1915 } catch (OperationCanceledException) {
1916 if (request != null)
1918 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, null, true, null));
1920 } catch (Exception ex) {
1921 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, true, null));
1922 throw new WebException ("An error occurred performing a WebClient request.", ex);
1926 async Task<byte[]> UploadFileTaskAsyncCore (WebRequest request, string method,
1927 string fileName, CancellationToken token)
1929 token.ThrowIfCancellationRequested ();
1931 string fileCType = Headers ["Content-Type"];
1932 if (fileCType != null) {
1933 string lower = fileCType.ToLower ();
1934 if (lower.StartsWith ("multipart/"))
1935 throw new WebException ("Content-Type cannot be set to a multipart" +
1936 " type for this request.");
1938 fileCType = "application/octet-stream";
1941 bool needs_boundary = (method != "PUT"); // only verified case so far
1942 string boundary = null;
1943 if (needs_boundary) {
1944 boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
1945 Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
1947 Stream reqStream = null;
1948 Stream fStream = null;
1949 WebResponse response = null;
1951 fileName = Path.GetFullPath (fileName);
1954 fStream = File.OpenRead (fileName);
1955 token.ThrowIfCancellationRequested ();
1956 reqStream = await request.GetRequestStreamAsync ();
1957 token.ThrowIfCancellationRequested ();
1958 byte [] bytes_boundary = null;
1959 if (needs_boundary) {
1960 bytes_boundary = Encoding.ASCII.GetBytes (boundary);
1961 using (MemoryStream ms = new MemoryStream ()) {
1962 ms.WriteByte ((byte) '-');
1963 ms.WriteByte ((byte) '-');
1964 ms.Write (bytes_boundary, 0, bytes_boundary.Length);
1965 ms.WriteByte ((byte) '\r');
1966 ms.WriteByte ((byte) '\n');
1967 string partHeaders = String.Format (
1968 "Content-Disposition: form-data; " +
1969 "name=\"file\"; filename=\"{0}\"\r\n" +
1970 "Content-Type: {1}\r\n\r\n",
1971 Path.GetFileName (fileName), fileCType);
1972 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
1973 ms.Write (partHeadersBytes, 0, partHeadersBytes.Length);
1974 await ms.CopyToAsync (reqStream, (int)ms.Position, token);
1978 long bytes_sent = 0;
1979 long file_size = -1;
1980 long step = 16384; // every 16kB
1981 if (fStream.CanSeek) {
1982 file_size = fStream.Length;
1983 step = file_size / 100;
1985 var upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, 0, null);
1986 OnUploadProgressChanged (upload_args);
1987 byte [] buffer = new byte [4096];
1989 token.ThrowIfCancellationRequested ();
1990 while ((nread = await fStream.ReadAsync (buffer, 0, 4096, token)) > 0) {
1991 token.ThrowIfCancellationRequested ();
1992 await reqStream.WriteAsync (buffer, 0, nread, token);
1993 bytes_sent += nread;
1995 if (sum >= step || nread < 4096) {
1998 percent = (int) (bytes_sent * 100 / file_size);
1999 upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, percent, null);
2000 OnUploadProgressChanged (upload_args);
2005 if (needs_boundary) {
2006 using (MemoryStream ms = new MemoryStream ()) {
2007 ms.WriteByte ((byte) '\r');
2008 ms.WriteByte ((byte) '\n');
2009 ms.WriteByte ((byte) '-');
2010 ms.WriteByte ((byte) '-');
2011 ms.Write (bytes_boundary, 0, bytes_boundary.Length);
2012 ms.WriteByte ((byte) '-');
2013 ms.WriteByte ((byte) '-');
2014 ms.WriteByte ((byte) '\r');
2015 ms.WriteByte ((byte) '\n');
2016 await ms.CopyToAsync (reqStream, (int)ms.Position, token);
2022 response = await GetWebResponseTaskAsync (request, token);
2023 return await ReadAllTaskAsync (request, response, token);
2025 if (fStream != null)
2028 if (reqStream != null)
2031 if (response != null)
2036 // UploadStringTaskAsync
2038 public Task<string> UploadStringTaskAsync (string address, string data)
2040 if (address == null)
2041 throw new ArgumentNullException ("address");
2043 throw new ArgumentNullException ("data");
2045 return UploadStringTaskAsync (CreateUri (address), null, data);
2048 public Task<string> UploadStringTaskAsync (string address, string method, string data)
2050 if (address == null)
2051 throw new ArgumentNullException ("address");
2053 throw new ArgumentNullException ("data");
2055 return UploadStringTaskAsync (CreateUri (address), method, data);
2058 public Task<string> UploadStringTaskAsync (Uri address, string data)
2060 if (address == null)
2061 throw new ArgumentNullException ("address");
2063 throw new ArgumentNullException ("data");
2065 return UploadStringTaskAsync (address, null, data);
2068 public async Task<string> UploadStringTaskAsync (Uri address, string method, string data)
2070 if (address == null)
2071 throw new ArgumentNullException ("address");
2073 throw new ArgumentNullException ("data");
2075 WebRequest request = null;
2078 cts = new CancellationTokenSource ();
2079 request = await SetupRequestAsync (address, method, true);
2080 var result = await UploadDataTaskAsyncCore (request, encoding.GetBytes (data), cts.Token);
2081 var result_str = encoding.GetString (result);
2082 OnUploadStringCompleted (new UploadStringCompletedEventArgs (result_str, null, false, null));
2084 } catch (WebException ex) {
2085 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, ex, false, null));
2087 } catch (OperationCanceledException) {
2088 if (request != null)
2090 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, null, true, null));
2092 } catch (Exception ex) {
2093 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, ex, true, null));
2094 throw new WebException ("An error occurred performing a WebClient request.", ex);
2098 // UploadValuesTaskAsync
2100 public Task<byte[]> UploadValuesTaskAsync (string address, NameValueCollection data)
2102 if (address == null)
2103 throw new ArgumentNullException ("address");
2105 return UploadValuesTaskAsync (CreateUri (address), data);
2108 public Task<byte[]> UploadValuesTaskAsync (string address, string method, NameValueCollection data)
2110 if (address == null)
2111 throw new ArgumentNullException ("address");
2113 return UploadValuesTaskAsync (CreateUri (address), method, data);
2116 public Task<byte[]> UploadValuesTaskAsync (Uri address, NameValueCollection data)
2118 return UploadValuesTaskAsync (address, (string) null, data);
2121 public async Task<byte[]> UploadValuesTaskAsync (Uri address, string method, NameValueCollection data)
2123 if (address == null)
2124 throw new ArgumentNullException ("address");
2126 throw new ArgumentNullException ("data");
2128 WebRequest request = null;
2131 cts = new CancellationTokenSource ();
2132 request = await SetupRequestAsync (address, method, true);
2133 var result = await UploadValuesTaskAsyncCore (request, data, cts.Token);
2134 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (result, null, false, null));
2136 } catch (WebException ex) {
2137 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, ex, false, null));
2139 } catch (OperationCanceledException) {
2140 if (request != null)
2142 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, null, true, null));
2144 } catch (Exception ex) {
2145 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, ex, true, null));
2146 throw new WebException ("An error occurred performing a WebClient request.", ex);
2150 async Task<byte[]> UploadValuesTaskAsyncCore (WebRequest request, NameValueCollection data,
2151 CancellationToken token)
2153 token.ThrowIfCancellationRequested ();
2154 string cType = Headers ["Content-Type"];
2155 if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
2156 throw new WebException ("Content-Type header cannot be changed from its default " +
2157 "value for this request.");
2159 WebResponse response = null;
2161 Headers ["Content-Type"] = urlEncodedCType;
2163 MemoryStream tmpStream = new MemoryStream ();
2164 foreach (string key in data) {
2165 byte [] bytes = Encoding.UTF8.GetBytes (key);
2166 UrlEncodeAndWrite (tmpStream, bytes);
2167 tmpStream.WriteByte ((byte) '=');
2168 bytes = Encoding.UTF8.GetBytes (data [key]);
2169 UrlEncodeAndWrite (tmpStream, bytes);
2170 tmpStream.WriteByte ((byte) '&');
2173 token.ThrowIfCancellationRequested ();
2175 int length = (int) tmpStream.Length;
2177 tmpStream.SetLength (--length); // remove trailing '&'
2179 byte [] buf = tmpStream.GetBuffer ();
2180 request.ContentLength = length;
2181 using (Stream rqStream = await request.GetRequestStreamAsync ()) {
2182 await rqStream.WriteAsync (buf, 0, length, token);
2186 response = await GetWebResponseTaskAsync (request, token);
2187 return await ReadAllTaskAsync (request, response, token);
2189 if (response != null)