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)
10 // Marek Safar (marek.safar@gmail.com)
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)
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:
25 // The above copyright notice and this permission notice shall be
26 // included in all copies or substantial portions of the Software.
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.
37 // Notes on CancelAsync and Async methods:
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.
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.
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.
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).
65 using System.Collections.Specialized;
66 using System.ComponentModel;
68 using System.Runtime.InteropServices;
69 using System.Runtime.Serialization;
71 using System.Threading;
72 using System.Net.Cache;
74 using System.Threading.Tasks;
80 public class WebClient : Component
82 static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
83 static byte [] hexBytes;
84 ICredentials credentials;
85 WebHeaderCollection headers;
86 WebHeaderCollection responseHeaders;
89 NameValueCollection queryString;
92 bool proxySet = false;
94 Encoding encoding = Encoding.Default;
96 // RequestCachePolicy cache_policy;
98 CancellationTokenSource cts;
104 hexBytes = new byte [16];
106 for (int i = '0'; i <= '9'; i++, index++)
107 hexBytes [index] = (byte) i;
109 for (int i = 'a'; i <= 'f'; i++, index++)
110 hexBytes [index] = (byte) i;
119 public string BaseAddress {
121 if (baseString == null) {
122 if (baseAddress == null)
126 baseString = baseAddress.ToString ();
131 if (value == null || value.Length == 0) {
134 baseAddress = new Uri (value);
139 static Exception GetMustImplement ()
141 return new NotImplementedException ();
144 [MonoTODO ("Value can be set but is currently ignored")]
145 public RequestCachePolicy CachePolicy
148 throw GetMustImplement ();
150 set { /*cache_policy = value;*/ }
153 [MonoTODO ("Value can be set but is ignored")]
154 public bool UseDefaultCredentials
157 throw GetMustImplement ();
160 // This makes no sense in mono
164 public ICredentials Credentials {
165 get { return credentials; }
166 set { credentials = value; }
169 public WebHeaderCollection Headers {
172 headers = new WebHeaderCollection ();
176 set { headers = value; }
179 public NameValueCollection QueryString {
181 if (queryString == null)
182 queryString = new NameValueCollection ();
186 set { queryString = value; }
189 public WebHeaderCollection ResponseHeaders {
190 get { return responseHeaders; }
193 public Encoding Encoding {
194 get { return encoding; }
197 throw new ArgumentNullException ("Encoding");
202 public IWebProxy Proxy {
205 return WebRequest.DefaultWebProxy;
218 return is_busy || (cts != null);
229 throw new NotSupportedException ("WebClient does not support concurrent I/O operations.");
242 public byte [] DownloadData (string address)
245 throw new ArgumentNullException ("address");
247 return DownloadData (CreateUri (address));
250 public byte [] DownloadData (Uri address)
253 throw new ArgumentNullException ("address");
258 return DownloadDataCore (address, null);
264 byte [] DownloadDataCore (Uri address, object userToken)
266 WebRequest request = null;
269 request = SetupRequest (address);
270 return ReadAll (request, userToken);
271 } catch (ThreadInterruptedException){
274 throw new WebException ("User canceled the request", WebExceptionStatus.RequestCanceled);
275 } catch (WebException) {
277 } catch (Exception ex) {
278 throw new WebException ("An error occurred performing a WebClient request.", ex);
284 public void DownloadFile (string address, string fileName)
287 throw new ArgumentNullException ("address");
289 DownloadFile (CreateUri (address), fileName);
292 public void DownloadFile (Uri address, string fileName)
295 throw new ArgumentNullException ("address");
296 if (fileName == null)
297 throw new ArgumentNullException ("fileName");
302 DownloadFileCore (address, fileName, null);
303 } catch (WebException) {
305 } catch (Exception ex) {
306 throw new WebException ("An error occurred " +
307 "performing a WebClient request.", ex);
313 void DownloadFileCore (Uri address, string fileName, object userToken)
315 WebRequest request = null;
317 using (FileStream f = new FileStream (fileName, FileMode.Create)) {
319 request = SetupRequest (address);
320 WebResponse response = GetWebResponse (request);
321 Stream st = response.GetResponseStream ();
323 int cLength = (int) response.ContentLength;
324 int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
325 byte [] buffer = new byte [length];
328 long notify_total = 0;
329 while ((nread = st.Read (buffer, 0, length)) != 0){
331 notify_total += nread;
332 OnDownloadProgressChanged (
333 new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, userToken));
336 f.Write (buffer, 0, nread);
338 } catch (ThreadInterruptedException){
348 public Stream OpenRead (string address)
351 throw new ArgumentNullException ("address");
352 return OpenRead (CreateUri (address));
355 public Stream OpenRead (Uri address)
358 throw new ArgumentNullException ("address");
360 WebRequest request = null;
364 request = SetupRequest (address);
365 WebResponse response = GetWebResponse (request);
366 return response.GetResponseStream ();
367 } catch (WebException) {
369 } catch (Exception ex) {
370 throw new WebException ("An error occurred " +
371 "performing a WebClient request.", ex);
379 public Stream OpenWrite (string address)
382 throw new ArgumentNullException ("address");
384 return OpenWrite (CreateUri (address));
387 public Stream OpenWrite (string address, string method)
390 throw new ArgumentNullException ("address");
392 return OpenWrite (CreateUri (address), method);
395 public Stream OpenWrite (Uri address)
397 return OpenWrite (address, (string) null);
400 public Stream OpenWrite (Uri address, string method)
403 throw new ArgumentNullException ("address");
408 WebRequest request = SetupRequest (address, method, true);
409 return request.GetRequestStream ();
410 } catch (WebException) {
412 } catch (Exception ex) {
413 throw new WebException ("An error occurred " +
414 "performing a WebClient request.", ex);
420 private string DetermineMethod (Uri address, string method, bool is_upload)
425 if (address.Scheme == Uri.UriSchemeFtp)
426 return (is_upload) ? "STOR" : "RETR";
428 return (is_upload) ? "POST" : "GET";
433 public byte [] UploadData (string address, byte [] data)
436 throw new ArgumentNullException ("address");
438 return UploadData (CreateUri (address), data);
441 public byte [] UploadData (string address, string method, byte [] data)
444 throw new ArgumentNullException ("address");
446 return UploadData (CreateUri (address), method, data);
449 public byte [] UploadData (Uri address, byte [] data)
451 return UploadData (address, (string) null, data);
454 public byte [] UploadData (Uri address, string method, byte [] data)
457 throw new ArgumentNullException ("address");
459 throw new ArgumentNullException ("data");
464 return UploadDataCore (address, method, data, null);
465 } catch (WebException) {
467 } catch (Exception ex) {
468 throw new WebException ("An error occurred " +
469 "performing a WebClient request.", ex);
475 byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
477 WebRequest request = SetupRequest (address, method, true);
479 int contentLength = data.Length;
480 request.ContentLength = contentLength;
481 using (Stream stream = request.GetRequestStream ()) {
482 stream.Write (data, 0, contentLength);
485 return ReadAll (request, userToken);
486 } catch (ThreadInterruptedException){
495 public byte [] UploadFile (string address, string fileName)
498 throw new ArgumentNullException ("address");
500 return UploadFile (CreateUri (address), fileName);
503 public byte [] UploadFile (Uri address, string fileName)
505 return UploadFile (address, (string) null, fileName);
508 public byte [] UploadFile (string address, string method, string fileName)
510 return UploadFile (CreateUri (address), method, fileName);
513 public byte [] UploadFile (Uri address, string method, string fileName)
516 throw new ArgumentNullException ("address");
517 if (fileName == null)
518 throw new ArgumentNullException ("fileName");
523 return UploadFileCore (address, method, fileName, null);
524 } catch (WebException) {
526 } catch (Exception ex) {
527 throw new WebException ("An error occurred " +
528 "performing a WebClient request.", ex);
534 byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
536 string fileCType = Headers ["Content-Type"];
537 if (fileCType != null) {
538 string lower = fileCType.ToLower ();
539 if (lower.StartsWith ("multipart/"))
540 throw new WebException ("Content-Type cannot be set to a multipart" +
541 " type for this request.");
543 fileCType = "application/octet-stream";
546 bool needs_boundary = (method != "PUT"); // only verified case so far
547 string boundary = null;
548 if (needs_boundary) {
549 boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
550 Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
552 Stream reqStream = null;
553 Stream fStream = null;
554 byte [] resultBytes = null;
556 fileName = Path.GetFullPath (fileName);
558 WebRequest request = null;
560 fStream = File.OpenRead (fileName);
561 request = SetupRequest (address, method, true);
562 reqStream = request.GetRequestStream ();
563 byte [] bytes_boundary = null;
564 if (needs_boundary) {
565 bytes_boundary = Encoding.ASCII.GetBytes (boundary);
566 reqStream.WriteByte ((byte) '-');
567 reqStream.WriteByte ((byte) '-');
568 reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
569 reqStream.WriteByte ((byte) '\r');
570 reqStream.WriteByte ((byte) '\n');
571 string partHeaders = String.Format ("Content-Disposition: form-data; " +
572 "name=\"file\"; filename=\"{0}\"\r\n" +
573 "Content-Type: {1}\r\n\r\n",
574 Path.GetFileName (fileName), fileCType);
576 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
577 reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
582 long step = 16384; // every 16kB
583 if (fStream.CanSeek) {
584 file_size = fStream.Length;
585 step = file_size / 100;
587 var upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, 0, userToken);
588 OnUploadProgressChanged (upload_args);
589 byte [] buffer = new byte [4096];
591 while ((nread = fStream.Read (buffer, 0, 4096)) > 0) {
592 reqStream.Write (buffer, 0, nread);
595 if (sum >= step || nread < 4096) {
598 percent = (int) (bytes_sent * 100 / file_size);
599 upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, percent, userToken);
600 OnUploadProgressChanged (upload_args);
605 if (needs_boundary) {
606 reqStream.WriteByte ((byte) '\r');
607 reqStream.WriteByte ((byte) '\n');
608 reqStream.WriteByte ((byte) '-');
609 reqStream.WriteByte ((byte) '-');
610 reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
611 reqStream.WriteByte ((byte) '-');
612 reqStream.WriteByte ((byte) '-');
613 reqStream.WriteByte ((byte) '\r');
614 reqStream.WriteByte ((byte) '\n');
618 resultBytes = ReadAll (request, userToken);
619 } catch (ThreadInterruptedException){
627 if (reqStream != null)
634 public byte[] UploadValues (string address, NameValueCollection data)
637 throw new ArgumentNullException ("address");
639 return UploadValues (CreateUri (address), data);
642 public byte[] UploadValues (string address, string method, NameValueCollection data)
645 throw new ArgumentNullException ("address");
646 return UploadValues (CreateUri (address), method, data);
649 public byte[] UploadValues (Uri address, NameValueCollection data)
651 return UploadValues (address, (string) null, data);
654 public byte[] UploadValues (Uri address, string method, NameValueCollection data)
657 throw new ArgumentNullException ("address");
659 throw new ArgumentNullException ("data");
664 return UploadValuesCore (address, method, data, null);
665 } catch (WebException) {
667 } catch (Exception ex) {
668 throw new WebException ("An error occurred " +
669 "performing a WebClient request.", ex);
675 byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
677 string cType = Headers ["Content-Type"];
678 if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
679 throw new WebException ("Content-Type header cannot be changed from its default " +
680 "value for this request.");
682 Headers ["Content-Type"] = urlEncodedCType;
683 WebRequest request = SetupRequest (uri, method, true);
685 MemoryStream tmpStream = new MemoryStream ();
686 foreach (string key in data) {
687 byte [] bytes = Encoding.UTF8.GetBytes (key);
688 UrlEncodeAndWrite (tmpStream, bytes);
689 tmpStream.WriteByte ((byte) '=');
690 bytes = Encoding.UTF8.GetBytes (data [key]);
691 UrlEncodeAndWrite (tmpStream, bytes);
692 tmpStream.WriteByte ((byte) '&');
695 int length = (int) tmpStream.Length;
697 tmpStream.SetLength (--length); // remove trailing '&'
699 byte [] buf = tmpStream.GetBuffer ();
700 request.ContentLength = length;
701 using (Stream rqStream = request.GetRequestStream ()) {
702 rqStream.Write (buf, 0, length);
706 return ReadAll (request, userToken);
707 } catch (ThreadInterruptedException) {
713 public string DownloadString (string address)
716 throw new ArgumentNullException ("address");
718 return encoding.GetString (DownloadData (CreateUri (address)));
721 public string DownloadString (Uri address)
724 throw new ArgumentNullException ("address");
726 return encoding.GetString (DownloadData (CreateUri (address)));
729 public string UploadString (string address, string data)
732 throw new ArgumentNullException ("address");
734 throw new ArgumentNullException ("data");
736 byte [] resp = UploadData (address, encoding.GetBytes (data));
737 return encoding.GetString (resp);
740 public string UploadString (string address, string method, string data)
743 throw new ArgumentNullException ("address");
745 throw new ArgumentNullException ("data");
747 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
748 return encoding.GetString (resp);
751 public string UploadString (Uri address, string data)
754 throw new ArgumentNullException ("address");
756 throw new ArgumentNullException ("data");
758 byte [] resp = UploadData (address, encoding.GetBytes (data));
759 return encoding.GetString (resp);
762 public string UploadString (Uri address, string method, string data)
765 throw new ArgumentNullException ("address");
767 throw new ArgumentNullException ("data");
769 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
770 return encoding.GetString (resp);
773 public event DownloadDataCompletedEventHandler DownloadDataCompleted;
774 public event AsyncCompletedEventHandler DownloadFileCompleted;
775 public event DownloadProgressChangedEventHandler DownloadProgressChanged;
776 public event DownloadStringCompletedEventHandler DownloadStringCompleted;
777 public event OpenReadCompletedEventHandler OpenReadCompleted;
778 public event OpenWriteCompletedEventHandler OpenWriteCompleted;
779 public event UploadDataCompletedEventHandler UploadDataCompleted;
780 public event UploadFileCompletedEventHandler UploadFileCompleted;
781 public event UploadProgressChangedEventHandler UploadProgressChanged;
782 public event UploadStringCompletedEventHandler UploadStringCompleted;
783 public event UploadValuesCompletedEventHandler UploadValuesCompleted;
785 Uri CreateUri (string address)
789 if (baseAddress == null)
790 uri = new Uri (address);
792 uri = new Uri (baseAddress, address);
793 return CreateUri (uri);
796 return new Uri (Path.GetFullPath (address));
799 Uri CreateUri (Uri address)
801 Uri result = address;
802 if (baseAddress != null && !result.IsAbsoluteUri) {
804 result = new Uri (baseAddress, result.OriginalString);
806 return result; // Not much we can do here.
810 string query = result.Query;
811 if (String.IsNullOrEmpty (query))
812 query = GetQueryString (true);
813 UriBuilder builder = new UriBuilder (address);
814 if (!String.IsNullOrEmpty (query))
815 builder.Query = query.Substring (1);
819 string GetQueryString (bool add_qmark)
821 if (queryString == null || queryString.Count == 0)
824 StringBuilder sb = new StringBuilder ();
828 foreach (string key in queryString)
829 sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
832 sb.Length--; // removes last '&' or the '?' if empty.
837 return sb.ToString ();
840 WebRequest SetupRequest (Uri uri)
842 WebRequest request = GetWebRequest (uri);
844 request.Proxy = Proxy;
845 if (credentials != null)
846 request.Credentials = credentials;
847 else if (!String.IsNullOrEmpty (uri.UserInfo)) {
848 // Perhaps this should be done by the underlying URI handler?
849 ICredentials creds = GetCredentials (uri.UserInfo);
851 request.Credentials = creds;
854 // Special headers. These are properties of HttpWebRequest.
855 // What do we do with other requests differnt from HttpWebRequest?
856 if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
857 HttpWebRequest req = (HttpWebRequest) request;
858 string expect = headers ["Expect"];
859 string contentType = headers ["Content-Type"];
860 string accept = headers ["Accept"];
861 string connection = headers ["Connection"];
862 string userAgent = headers ["User-Agent"];
863 string referer = headers ["Referer"];
864 headers.RemoveInternal ("Expect");
865 headers.RemoveInternal ("Content-Type");
866 headers.RemoveInternal ("Accept");
867 headers.RemoveInternal ("Connection");
868 headers.RemoveInternal ("Referer");
869 headers.RemoveInternal ("User-Agent");
870 request.Headers = headers;
872 if (expect != null && expect.Length > 0)
875 if (accept != null && accept.Length > 0)
878 if (contentType != null && contentType.Length > 0)
879 req.ContentType = contentType;
881 if (connection != null && connection.Length > 0)
882 req.Connection = connection;
884 if (userAgent != null && userAgent.Length > 0)
885 req.UserAgent = userAgent;
887 if (referer != null && referer.Length > 0)
888 req.Referer = referer;
891 responseHeaders = null;
895 WebRequest SetupRequest (Uri uri, string method, bool is_upload)
897 WebRequest request = SetupRequest (uri);
898 request.Method = DetermineMethod (uri, method, is_upload);
902 static NetworkCredential GetCredentials (string user_info)
904 string [] creds = user_info.Split (':');
905 if (creds.Length != 2)
908 if (creds [0].IndexOf ('\\') != -1) {
909 string [] user = creds [0].Split ('\\');
910 if (user.Length != 2)
912 return new NetworkCredential (user [1], creds [1], user [0]);
914 return new NetworkCredential (creds [0], creds [1]);
917 byte [] ReadAll (WebRequest request, object userToken)
919 WebResponse response = GetWebResponse (request);
920 Stream stream = response.GetResponseStream ();
921 int length = (int) response.ContentLength;
922 HttpWebRequest wreq = request as HttpWebRequest;
924 if (length > -1 && wreq != null && (int) wreq.AutomaticDecompression != 0) {
925 string content_encoding = ((HttpWebResponse) response).ContentEncoding;
926 if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
927 ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
931 MemoryStream ms = null;
932 bool nolength = (length == -1);
933 int size = ((nolength) ? 8192 : length);
935 ms = new MemoryStream ();
940 byte [] buffer = new byte [size];
941 while ((nread = stream.Read (buffer, offset, size)) != 0) {
943 ms.Write (buffer, 0, nread);
950 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, userToken));
955 return ms.ToArray ();
960 string UrlEncode (string str)
962 StringBuilder result = new StringBuilder ();
964 int len = str.Length;
965 for (int i = 0; i < len; i++) {
969 else if ((c < '0' && c != '-' && c != '.') ||
970 (c < 'A' && c > '9') ||
971 (c > 'Z' && c < 'a' && c != '_') ||
974 int idx = ((int) c) >> 4;
975 result.Append ((char) hexBytes [idx]);
976 idx = ((int) c) & 0x0F;
977 result.Append ((char) hexBytes [idx]);
983 return result.ToString ();
986 static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
991 int len = bytes.Length;
995 for (int i = 0; i < len; i++) {
996 char c = (char) bytes [i];
998 stream.WriteByte ((byte) '+');
999 else if ((c < '0' && c != '-' && c != '.') ||
1000 (c < 'A' && c > '9') ||
1001 (c > 'Z' && c < 'a' && c != '_') ||
1003 stream.WriteByte ((byte) '%');
1004 int idx = ((int) c) >> 4;
1005 stream.WriteByte (hexBytes [idx]);
1006 idx = ((int) c) & 0x0F;
1007 stream.WriteByte (hexBytes [idx]);
1009 stream.WriteByte ((byte) c);
1014 public void CancelAsync ()
1024 if (async_thread == null)
1028 // We first flag things as done, in case the Interrupt hangs
1029 // or the thread decides to hang in some other way inside the
1030 // event handlers, or if we are stuck somewhere else. This
1031 // ensures that the WebClient object is reusable immediately
1033 Thread t = async_thread;
1039 void CompleteAsync ()
1043 async_thread = null;
1052 // DownloadDataAsync
1054 public void DownloadDataAsync (Uri address)
1056 DownloadDataAsync (address, null);
1059 public void DownloadDataAsync (Uri address, object userToken)
1061 if (address == null)
1062 throw new ArgumentNullException ("address");
1068 async_thread = new Thread (delegate (object state) {
1069 object [] args = (object []) state;
1071 byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
1072 OnDownloadDataCompleted (
1073 new DownloadDataCompletedEventArgs (data, null, false, args [1]));
1074 } catch (Exception e){
1075 bool canceled = false;
1076 WebException we = e as WebException;
1078 canceled = we.Status == WebExceptionStatus.RequestCanceled;
1079 OnDownloadDataCompleted (
1080 new DownloadDataCompletedEventArgs (null, e, canceled, args [1]));
1083 object [] cb_args = new object [] { CreateUri (address), userToken };
1084 async_thread.IsBackground = true;
1085 async_thread.Start (cb_args);
1089 // DownloadFileAsync
1091 public void DownloadFileAsync (Uri address, string fileName)
1093 DownloadFileAsync (address, fileName, null);
1096 public void DownloadFileAsync (Uri address, string fileName, object userToken)
1098 if (address == null)
1099 throw new ArgumentNullException ("address");
1100 if (fileName == null)
1101 throw new ArgumentNullException ("fileName");
1107 async_thread = new Thread (delegate (object state) {
1108 object [] args = (object []) state;
1110 DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
1111 OnDownloadFileCompleted (
1112 new AsyncCompletedEventArgs (null, false, args [2]));
1113 } catch (ThreadInterruptedException){
1114 OnDownloadFileCompleted (
1115 new AsyncCompletedEventArgs (null, true, args [2]));
1116 } catch (Exception e){
1117 OnDownloadFileCompleted (
1118 new AsyncCompletedEventArgs (e, false, args [2]));
1120 object [] cb_args = new object [] { CreateUri (address), fileName, userToken };
1121 async_thread.IsBackground = true;
1122 async_thread.Start (cb_args);
1126 // DownloadStringAsync
1128 public void DownloadStringAsync (Uri address)
1130 DownloadStringAsync (address, null);
1133 public void DownloadStringAsync (Uri address, object userToken)
1135 if (address == null)
1136 throw new ArgumentNullException ("address");
1142 async_thread = new Thread (delegate (object state) {
1143 object [] args = (object []) state;
1145 string data = encoding.GetString (DownloadDataCore ((Uri) args [0], args [1]));
1146 OnDownloadStringCompleted (
1147 new DownloadStringCompletedEventArgs (data, null, false, args [1]));
1148 } catch (Exception e){
1149 bool canceled = false;
1150 WebException we = e as WebException;
1152 canceled = we.Status == WebExceptionStatus.RequestCanceled;
1153 OnDownloadStringCompleted (
1154 new DownloadStringCompletedEventArgs (null, e, canceled, args [1]));
1156 object [] cb_args = new object [] { CreateUri (address), userToken };
1157 async_thread.IsBackground = true;
1158 async_thread.Start (cb_args);
1164 public void OpenReadAsync (Uri address)
1166 OpenReadAsync (address, null);
1169 public void OpenReadAsync (Uri address, object userToken)
1171 if (address == null)
1172 throw new ArgumentNullException ("address");
1178 async_thread = new Thread (delegate (object state) {
1179 object [] args = (object []) state;
1180 WebRequest request = null;
1182 request = SetupRequest ((Uri) args [0]);
1183 WebResponse response = GetWebResponse (request);
1184 Stream stream = response.GetResponseStream ();
1185 OnOpenReadCompleted (
1186 new OpenReadCompletedEventArgs (stream, null, false, args [1]));
1187 } catch (ThreadInterruptedException){
1188 if (request != null)
1191 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, args [1]));
1192 } catch (Exception e){
1193 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, e, false, args [1]));
1195 object [] cb_args = new object [] { CreateUri (address), userToken };
1196 async_thread.IsBackground = true;
1197 async_thread.Start (cb_args);
1203 public void OpenWriteAsync (Uri address)
1205 OpenWriteAsync (address, null);
1208 public void OpenWriteAsync (Uri address, string method)
1210 OpenWriteAsync (address, method, null);
1213 public void OpenWriteAsync (Uri address, string method, object userToken)
1215 if (address == null)
1216 throw new ArgumentNullException ("address");
1222 async_thread = new Thread (delegate (object state) {
1223 object [] args = (object []) state;
1224 WebRequest request = null;
1226 request = SetupRequest ((Uri) args [0], (string) args [1], true);
1227 Stream stream = request.GetRequestStream ();
1228 OnOpenWriteCompleted (
1229 new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
1230 } catch (ThreadInterruptedException){
1231 if (request != null)
1233 OnOpenWriteCompleted (
1234 new OpenWriteCompletedEventArgs (null, null, true, args [2]));
1235 } catch (Exception e){
1236 OnOpenWriteCompleted (
1237 new OpenWriteCompletedEventArgs (null, e, false, args [2]));
1239 object [] cb_args = new object [] { CreateUri (address), method, userToken };
1240 async_thread.IsBackground = true;
1241 async_thread.Start (cb_args);
1247 public void UploadDataAsync (Uri address, byte [] data)
1249 UploadDataAsync (address, null, data);
1252 public void UploadDataAsync (Uri address, string method, byte [] data)
1254 UploadDataAsync (address, method, data, null);
1257 public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
1259 if (address == null)
1260 throw new ArgumentNullException ("address");
1262 throw new ArgumentNullException ("data");
1268 async_thread = new Thread (delegate (object state) {
1269 object [] args = (object []) state;
1273 data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
1275 OnUploadDataCompleted (
1276 new UploadDataCompletedEventArgs (data2, null, false, args [3]));
1277 } catch (ThreadInterruptedException){
1278 OnUploadDataCompleted (
1279 new UploadDataCompletedEventArgs (null, null, true, args [3]));
1280 } catch (Exception e){
1281 OnUploadDataCompleted (
1282 new UploadDataCompletedEventArgs (null, e, false, args [3]));
1284 object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
1285 async_thread.IsBackground = true;
1286 async_thread.Start (cb_args);
1292 public void UploadFileAsync (Uri address, string fileName)
1294 UploadFileAsync (address, null, fileName);
1297 public void UploadFileAsync (Uri address, string method, string fileName)
1299 UploadFileAsync (address, method, fileName, null);
1302 public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
1304 if (address == null)
1305 throw new ArgumentNullException ("address");
1306 if (fileName == null)
1307 throw new ArgumentNullException ("fileName");
1313 async_thread = new Thread (delegate (object state) {
1314 object [] args = (object []) state;
1318 data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
1319 OnUploadFileCompleted (
1320 new UploadFileCompletedEventArgs (data, null, false, args [3]));
1321 } catch (ThreadInterruptedException){
1322 OnUploadFileCompleted (
1323 new UploadFileCompletedEventArgs (null, null, true, args [3]));
1324 } catch (Exception e){
1325 OnUploadFileCompleted (
1326 new UploadFileCompletedEventArgs (null, e, false, args [3]));
1328 object [] cb_args = new object [] { CreateUri (address), method, fileName, userToken };
1329 async_thread.IsBackground = true;
1330 async_thread.Start (cb_args);
1334 // UploadStringAsync
1336 public void UploadStringAsync (Uri address, string data)
1338 UploadStringAsync (address, null, data);
1341 public void UploadStringAsync (Uri address, string method, string data)
1343 UploadStringAsync (address, method, data, null);
1346 public void UploadStringAsync (Uri address, string method, string data, object userToken)
1348 if (address == null)
1349 throw new ArgumentNullException ("address");
1351 throw new ArgumentNullException ("data");
1357 async_thread = new Thread (delegate (object state) {
1358 object [] args = (object []) state;
1361 string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
1362 OnUploadStringCompleted (
1363 new UploadStringCompletedEventArgs (data2, null, false, args [3]));
1364 } catch (ThreadInterruptedException){
1365 OnUploadStringCompleted (
1366 new UploadStringCompletedEventArgs (null, null, true, args [3]));
1367 } catch (Exception e){
1368 OnUploadStringCompleted (
1369 new UploadStringCompletedEventArgs (null, e, false, args [3]));
1371 object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
1372 async_thread.IsBackground = true;
1373 async_thread.Start (cb_args);
1377 // UploadValuesAsync
1379 public void UploadValuesAsync (Uri address, NameValueCollection data)
1381 UploadValuesAsync (address, null, data);
1384 public void UploadValuesAsync (Uri address, string method, NameValueCollection data)
1386 UploadValuesAsync (address, method, data, null);
1389 public void UploadValuesAsync (Uri address, string method, NameValueCollection data, object userToken)
1391 if (address == null)
1392 throw new ArgumentNullException ("address");
1394 throw new ArgumentNullException ("data");
1400 async_thread = new Thread (delegate (object state) {
1401 object [] args = (object []) state;
1403 byte [] values = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
1404 OnUploadValuesCompleted (
1405 new UploadValuesCompletedEventArgs (values, null, false, args [3]));
1406 } catch (ThreadInterruptedException){
1407 OnUploadValuesCompleted (
1408 new UploadValuesCompletedEventArgs (null, null, true, args [3]));
1409 } catch (Exception e){
1410 OnUploadValuesCompleted (
1411 new UploadValuesCompletedEventArgs (null, e, false, args [3]));
1413 object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
1414 async_thread.IsBackground = true;
1415 async_thread.Start (cb_args);
1419 protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs e)
1422 if (DownloadDataCompleted != null)
1423 DownloadDataCompleted (this, e);
1426 protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs e)
1429 if (DownloadFileCompleted != null)
1430 DownloadFileCompleted (this, e);
1433 protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
1435 if (DownloadProgressChanged != null)
1436 DownloadProgressChanged (this, e);
1439 protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs e)
1442 if (DownloadStringCompleted != null)
1443 DownloadStringCompleted (this, e);
1446 protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs e)
1449 if (OpenReadCompleted != null)
1450 OpenReadCompleted (this, e);
1453 protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs e)
1456 if (OpenWriteCompleted != null)
1457 OpenWriteCompleted (this, e);
1460 protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs e)
1463 if (UploadDataCompleted != null)
1464 UploadDataCompleted (this, e);
1467 protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs e)
1470 if (UploadFileCompleted != null)
1471 UploadFileCompleted (this, e);
1474 protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
1476 if (UploadProgressChanged != null)
1477 UploadProgressChanged (this, e);
1480 protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs e)
1483 if (UploadStringCompleted != null)
1484 UploadStringCompleted (this, e);
1487 protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs e)
1490 if (UploadValuesCompleted != null)
1491 UploadValuesCompleted (this, e);
1494 protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
1496 WebResponse response = request.EndGetResponse (result);
1497 responseHeaders = response.Headers;
1501 protected virtual WebRequest GetWebRequest (Uri address)
1503 return WebRequest.Create (address);
1506 protected virtual WebResponse GetWebResponse (WebRequest request)
1508 WebResponse response = request.GetResponse ();
1509 responseHeaders = response.Headers;
1515 // DownloadDataTaskAsync
1517 public Task<byte[]> DownloadDataTaskAsync (string address)
1519 return DownloadDataTaskAsync (CreateUri (address));
1522 public async Task<byte[]> DownloadDataTaskAsync (Uri address)
1524 WebRequest request = null;
1525 WebResponse response = null;
1528 cts = new CancellationTokenSource ();
1529 request = await SetupRequestAsync (address);
1530 response = await GetWebResponseTaskAsync (request, cts.Token);
1531 var result = await ReadAllTaskAsync (request, response, cts.Token);
1533 // Has to run on original context
1534 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (result, null, false, null));
1536 } catch (WebException ex) {
1537 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, false, null));
1539 } catch (OperationCanceledException) {
1540 if (request != null)
1542 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, null, true, null));
1544 } catch (Exception ex) {
1545 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, true, null));
1546 throw new WebException ("An error occurred performing a WebClient request.", ex);
1548 if (response != null)
1553 Task<WebRequest> SetupRequestAsync (Uri address)
1555 return Task.Factory.StartNew (() => SetupRequest (address));
1558 async Task<WebRequest> SetupRequestAsync (Uri address, string method, bool is_upload)
1560 WebRequest request = await SetupRequestAsync (address).ConfigureAwait (false);
1561 request.Method = DetermineMethod (address, method, is_upload);
1565 async Task<WebResponse> GetWebResponseTaskAsync (WebRequest request, CancellationToken token)
1567 token.ThrowIfCancellationRequested ();
1568 WebResponse response = await request.GetResponseAsync ().ConfigureAwait (false);
1569 token.ThrowIfCancellationRequested ();
1570 responseHeaders = response.Headers;
1574 async Task<byte[]> ReadAllTaskAsync (WebRequest request, WebResponse response, CancellationToken token)
1576 Stream stream = response.GetResponseStream ();
1577 int length = (int)response.ContentLength;
1578 HttpWebRequest wreq = request as HttpWebRequest;
1580 if (length > -1 && wreq != null && (int)wreq.AutomaticDecompression != 0) {
1581 string content_encoding = ((HttpWebResponse)response).ContentEncoding;
1582 if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
1583 ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
1587 MemoryStream ms = null;
1588 bool nolength = (length == -1);
1589 int size = ((nolength) ? 8192 : length);
1591 ms = new MemoryStream ();
1596 byte [] buffer = new byte [size];
1597 token.ThrowIfCancellationRequested ();
1598 while ((nread = await stream.ReadAsync (buffer, offset, size, token)) != 0) {
1600 ms.Write (buffer, 0, nread);
1606 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, null));
1607 token.ThrowIfCancellationRequested ();
1610 return nolength ? ms.ToArray () : buffer;
1613 // DownloadFileTaskAsync
1615 public Task DownloadFileTaskAsync (string address, string fileName)
1617 if (address == null)
1618 throw new ArgumentNullException ("address");
1620 return DownloadFileTaskAsync (CreateUri (address), fileName);
1623 public async Task DownloadFileTaskAsync (Uri address, string fileName)
1625 if (address == null)
1626 throw new ArgumentNullException ("address");
1627 if (fileName == null)
1628 throw new ArgumentNullException ("fileName");
1630 WebRequest request = null;
1631 WebResponse response = null;
1635 cts = new CancellationTokenSource ();
1636 request = await SetupRequestAsync (address);
1637 response = await GetWebResponseTaskAsync (request, cts.Token);
1638 await DownloadFileTaskAsyncCore (request, response, fileName, cts.Token);
1639 OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, false, null));
1640 } catch (WebException ex) {
1641 OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
1643 } catch (OperationCanceledException) {
1644 if (request != null)
1646 OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, true, null));
1648 } catch (Exception ex) {
1649 OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
1650 throw new WebException ("An error occurred " +
1651 "performing a WebClient request.", ex);
1653 if (response != null)
1658 async Task DownloadFileTaskAsyncCore (WebRequest request, WebResponse response,
1659 string fileName, CancellationToken token)
1661 using (FileStream f = new FileStream (fileName, FileMode.Create)) {
1662 Stream st = response.GetResponseStream ();
1664 int cLength = (int)response.ContentLength;
1665 int length = (cLength <= -1 || cLength > 32 * 1024) ? 32 * 1024 : cLength;
1666 byte [] buffer = new byte [length];
1669 long notify_total = 0;
1670 token.ThrowIfCancellationRequested ();
1671 while ((nread = await st.ReadAsync (buffer, 0, length, token)) != 0) {
1672 notify_total += nread;
1673 OnDownloadProgressChanged (
1674 new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, null));
1675 token.ThrowIfCancellationRequested ();
1676 await f.WriteAsync (buffer, 0, nread, token);
1677 token.ThrowIfCancellationRequested ();
1682 // OpenReadTaskAsync
1684 public Task<Stream> OpenReadTaskAsync (string address)
1686 if (address == null)
1687 throw new ArgumentNullException ("address");
1688 return OpenReadTaskAsync (CreateUri (address));
1691 public async Task<Stream> OpenReadTaskAsync (Uri address)
1693 if (address == null)
1694 throw new ArgumentNullException ("address");
1696 WebRequest request = null;
1699 cts = new CancellationTokenSource ();
1700 request = await SetupRequestAsync (address);
1701 WebResponse response = await GetWebResponseTaskAsync (request, cts.Token);
1702 var result = response.GetResponseStream ();
1703 cts.Token.ThrowIfCancellationRequested ();
1704 OnOpenReadCompleted (new OpenReadCompletedEventArgs (result, null, false, null));
1706 } catch (WebException ex) {
1707 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
1709 } catch (OperationCanceledException) {
1710 if (request != null)
1712 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, null));
1714 } catch (Exception ex) {
1715 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
1716 throw new WebException ("An error occurred " +
1717 "performing a WebClient request.", ex);
1721 // DownloadStringTaskAsync
1723 public Task<string> DownloadStringTaskAsync (string address)
1725 if (address == null)
1726 throw new ArgumentNullException ("address");
1728 return DownloadStringTaskAsync (CreateUri (address));
1731 public async Task<string> DownloadStringTaskAsync (Uri address)
1733 if (address == null)
1734 throw new ArgumentNullException ("address");
1736 WebRequest request = null;
1737 WebResponse response = null;
1741 cts = new CancellationTokenSource ();
1742 request = await SetupRequestAsync (address);
1743 response = await GetWebResponseTaskAsync (request, cts.Token);
1744 var data = await ReadAllTaskAsync (request, response, cts.Token);
1745 cts.Token.ThrowIfCancellationRequested ();
1746 var text = encoding.GetString (data);
1747 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (text, null, false, null));
1749 } catch (WebException ex) {
1750 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, ex, false, null));
1752 } catch (OperationCanceledException) {
1753 if (request != null)
1755 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, null, true, null));
1757 } catch (Exception ex) {
1758 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, ex, true, null));
1759 throw new WebException ("An error occurred performing a WebClient request.", ex);
1761 if (response != null)
1766 // OpenWriteTaskAsync
1768 public Task<Stream> OpenWriteTaskAsync (string address)
1770 if (address == null)
1771 throw new ArgumentNullException ("address");
1773 return OpenWriteTaskAsync (CreateUri (address));
1776 public Task<Stream> OpenWriteTaskAsync (string address, string method)
1778 if (address == null)
1779 throw new ArgumentNullException ("address");
1781 return OpenWriteTaskAsync (CreateUri (address), method);
1784 public Task<Stream> OpenWriteTaskAsync (Uri address)
1786 return OpenWriteTaskAsync (address, (string) null);
1789 public async Task<Stream> OpenWriteTaskAsync (Uri address, string method)
1791 if (address == null)
1792 throw new ArgumentNullException ("address");
1794 WebRequest request = null;
1797 cts = new CancellationTokenSource ();
1798 request = SetupRequest (address);
1799 return await request.GetRequestStreamAsync ().ConfigureAwait (false);
1800 } catch (WebException) {
1802 } catch (OperationCanceledException) {
1803 if (request != null)
1806 } catch (Exception ex) {
1807 throw new WebException ("An error occurred " +
1808 "performing a WebClient request.", ex);
1814 // UploadDataTaskAsync
1816 public Task<byte[]> UploadDataTaskAsync (string address, byte [] data)
1818 if (address == null)
1819 throw new ArgumentNullException ("address");
1821 return UploadDataTaskAsync (CreateUri (address), data);
1824 public Task<byte[]> UploadDataTaskAsync (string address, string method, byte [] data)
1826 if (address == null)
1827 throw new ArgumentNullException ("address");
1829 return UploadDataTaskAsync (CreateUri (address), method, data);
1832 public Task<byte[]> UploadDataTaskAsync (Uri address, byte [] data)
1834 return UploadDataTaskAsync (address, (string) null, data);
1837 public async Task<byte[]> UploadDataTaskAsync (Uri address, string method, byte [] data)
1839 if (address == null)
1840 throw new ArgumentNullException ("address");
1842 throw new ArgumentNullException ("data");
1844 WebRequest request = null;
1847 cts = new CancellationTokenSource ();
1848 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
1849 var result = await UploadDataTaskAsyncCore (request, data, cts.Token).ConfigureAwait (false);
1850 OnUploadDataCompleted (new UploadDataCompletedEventArgs (result, null, false, null));
1852 } catch (WebException ex) {
1853 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, ex, false, null));
1855 } catch (OperationCanceledException) {
1856 if (request != null)
1858 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, null, true, null));
1860 } catch (Exception ex) {
1861 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, ex, true, null));
1862 throw new WebException ("An error occurred performing a WebClient request.", ex);
1866 async Task<byte[]> UploadDataTaskAsyncCore (WebRequest request, byte[] data, CancellationToken token)
1868 token.ThrowIfCancellationRequested ();
1870 int contentLength = data.Length;
1871 request.ContentLength = contentLength;
1872 using (Stream stream = await request.GetRequestStreamAsync ().ConfigureAwait (false)) {
1873 token.ThrowIfCancellationRequested ();
1874 await stream.WriteAsync (data, 0, contentLength, token).ConfigureAwait (false);
1875 token.ThrowIfCancellationRequested ();
1878 WebResponse response = null;
1881 response = await GetWebResponseTaskAsync (request, token).ConfigureAwait (false);
1882 return await ReadAllTaskAsync (request, response, token).ConfigureAwait (false);
1884 if (response != null)
1889 // UploadFileTaskAsync
1891 public Task<byte[]> UploadFileTaskAsync (string address, string fileName)
1893 if (address == null)
1894 throw new ArgumentNullException ("address");
1896 return UploadFileTaskAsync (CreateUri (address), fileName);
1899 public Task<byte[]> UploadFileTaskAsync (Uri address, string fileName)
1901 return UploadFileTaskAsync (address, (string) null, fileName);
1904 public Task<byte[]> UploadFileTaskAsync (string address, string method, string fileName)
1906 return UploadFileTaskAsync (CreateUri (address), method, fileName);
1909 public async Task<byte[]> UploadFileTaskAsync (Uri address, string method, string fileName)
1911 if (address == null)
1912 throw new ArgumentNullException ("address");
1913 if (fileName == null)
1914 throw new ArgumentNullException ("fileName");
1916 WebRequest request = null;
1919 cts = new CancellationTokenSource ();
1920 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
1921 var result = await UploadFileTaskAsyncCore (request, method, fileName, cts.Token).ConfigureAwait (false);
1922 OnUploadFileCompleted (new UploadFileCompletedEventArgs (result, null, false, null));
1924 } catch (WebException ex) {
1925 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, false, null));
1927 } catch (OperationCanceledException) {
1928 if (request != null)
1930 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, null, true, null));
1932 } catch (Exception ex) {
1933 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, true, null));
1934 throw new WebException ("An error occurred performing a WebClient request.", ex);
1938 async Task<byte[]> UploadFileTaskAsyncCore (WebRequest request, string method,
1939 string fileName, CancellationToken token)
1941 token.ThrowIfCancellationRequested ();
1943 string fileCType = Headers ["Content-Type"];
1944 if (fileCType != null) {
1945 string lower = fileCType.ToLower ();
1946 if (lower.StartsWith ("multipart/"))
1947 throw new WebException ("Content-Type cannot be set to a multipart" +
1948 " type for this request.");
1950 fileCType = "application/octet-stream";
1953 bool needs_boundary = (method != "PUT"); // only verified case so far
1954 string boundary = null;
1955 if (needs_boundary) {
1956 boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
1957 Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
1959 Stream reqStream = null;
1960 Stream fStream = null;
1961 WebResponse response = null;
1963 fileName = Path.GetFullPath (fileName);
1966 fStream = File.OpenRead (fileName);
1967 token.ThrowIfCancellationRequested ();
1968 reqStream = await request.GetRequestStreamAsync ().ConfigureAwait (false);
1969 token.ThrowIfCancellationRequested ();
1970 byte [] bytes_boundary = null;
1971 if (needs_boundary) {
1972 bytes_boundary = Encoding.ASCII.GetBytes (boundary);
1973 using (MemoryStream ms = new MemoryStream ()) {
1974 ms.WriteByte ((byte) '-');
1975 ms.WriteByte ((byte) '-');
1976 ms.Write (bytes_boundary, 0, bytes_boundary.Length);
1977 ms.WriteByte ((byte) '\r');
1978 ms.WriteByte ((byte) '\n');
1979 string partHeaders = String.Format (
1980 "Content-Disposition: form-data; " +
1981 "name=\"file\"; filename=\"{0}\"\r\n" +
1982 "Content-Type: {1}\r\n\r\n",
1983 Path.GetFileName (fileName), fileCType);
1984 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
1985 ms.Write (partHeadersBytes, 0, partHeadersBytes.Length);
1986 await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
1990 long bytes_sent = 0;
1991 long file_size = -1;
1992 long step = 16384; // every 16kB
1993 if (fStream.CanSeek) {
1994 file_size = fStream.Length;
1995 step = file_size / 100;
1997 var upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, 0, null);
1998 OnUploadProgressChanged (upload_args);
1999 byte [] buffer = new byte [4096];
2001 token.ThrowIfCancellationRequested ();
2002 while ((nread = await fStream.ReadAsync (buffer, 0, 4096, token).ConfigureAwait (false)) > 0) {
2003 token.ThrowIfCancellationRequested ();
2004 await reqStream.WriteAsync (buffer, 0, nread, token).ConfigureAwait (false);
2005 bytes_sent += nread;
2007 if (sum >= step || nread < 4096) {
2010 percent = (int) (bytes_sent * 100 / file_size);
2011 upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, percent, null);
2012 OnUploadProgressChanged (upload_args);
2017 if (needs_boundary) {
2018 using (MemoryStream ms = new MemoryStream ()) {
2019 ms.WriteByte ((byte) '\r');
2020 ms.WriteByte ((byte) '\n');
2021 ms.WriteByte ((byte) '-');
2022 ms.WriteByte ((byte) '-');
2023 ms.Write (bytes_boundary, 0, bytes_boundary.Length);
2024 ms.WriteByte ((byte) '-');
2025 ms.WriteByte ((byte) '-');
2026 ms.WriteByte ((byte) '\r');
2027 ms.WriteByte ((byte) '\n');
2028 await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
2034 response = await GetWebResponseTaskAsync (request, token).ConfigureAwait (false);
2035 return await ReadAllTaskAsync (request, response, token).ConfigureAwait (false);
2037 if (fStream != null)
2040 if (reqStream != null)
2043 if (response != null)
2048 // UploadStringTaskAsync
2050 public Task<string> UploadStringTaskAsync (string address, string data)
2052 if (address == null)
2053 throw new ArgumentNullException ("address");
2055 throw new ArgumentNullException ("data");
2057 return UploadStringTaskAsync (CreateUri (address), null, data);
2060 public Task<string> UploadStringTaskAsync (string address, string method, string data)
2062 if (address == null)
2063 throw new ArgumentNullException ("address");
2065 throw new ArgumentNullException ("data");
2067 return UploadStringTaskAsync (CreateUri (address), method, data);
2070 public Task<string> UploadStringTaskAsync (Uri address, string data)
2072 if (address == null)
2073 throw new ArgumentNullException ("address");
2075 throw new ArgumentNullException ("data");
2077 return UploadStringTaskAsync (address, null, data);
2080 public async Task<string> UploadStringTaskAsync (Uri address, string method, string data)
2082 if (address == null)
2083 throw new ArgumentNullException ("address");
2085 throw new ArgumentNullException ("data");
2087 WebRequest request = null;
2090 cts = new CancellationTokenSource ();
2091 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
2092 var result = await UploadDataTaskAsyncCore (request, encoding.GetBytes (data), cts.Token).ConfigureAwait (false);
2093 var result_str = encoding.GetString (result);
2094 OnUploadStringCompleted (new UploadStringCompletedEventArgs (result_str, null, false, null));
2096 } catch (WebException ex) {
2097 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, ex, false, null));
2099 } catch (OperationCanceledException) {
2100 if (request != null)
2102 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, null, true, null));
2104 } catch (Exception ex) {
2105 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, ex, true, null));
2106 throw new WebException ("An error occurred performing a WebClient request.", ex);
2110 // UploadValuesTaskAsync
2112 public Task<byte[]> UploadValuesTaskAsync (string address, NameValueCollection data)
2114 if (address == null)
2115 throw new ArgumentNullException ("address");
2117 return UploadValuesTaskAsync (CreateUri (address), data);
2120 public Task<byte[]> UploadValuesTaskAsync (string address, string method, NameValueCollection data)
2122 if (address == null)
2123 throw new ArgumentNullException ("address");
2125 return UploadValuesTaskAsync (CreateUri (address), method, data);
2128 public Task<byte[]> UploadValuesTaskAsync (Uri address, NameValueCollection data)
2130 return UploadValuesTaskAsync (address, (string) null, data);
2133 public async Task<byte[]> UploadValuesTaskAsync (Uri address, string method, NameValueCollection data)
2135 if (address == null)
2136 throw new ArgumentNullException ("address");
2138 throw new ArgumentNullException ("data");
2140 WebRequest request = null;
2143 cts = new CancellationTokenSource ();
2144 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
2145 var result = await UploadValuesTaskAsyncCore (request, data, cts.Token).ConfigureAwait (false);
2146 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (result, null, false, null));
2148 } catch (WebException ex) {
2149 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, ex, false, null));
2151 } catch (OperationCanceledException) {
2152 if (request != null)
2154 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, null, true, null));
2156 } catch (Exception ex) {
2157 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, ex, true, null));
2158 throw new WebException ("An error occurred performing a WebClient request.", ex);
2162 async Task<byte[]> UploadValuesTaskAsyncCore (WebRequest request, NameValueCollection data,
2163 CancellationToken token)
2165 token.ThrowIfCancellationRequested ();
2166 string cType = Headers ["Content-Type"];
2167 if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
2168 throw new WebException ("Content-Type header cannot be changed from its default " +
2169 "value for this request.");
2171 WebResponse response = null;
2173 Headers ["Content-Type"] = urlEncodedCType;
2175 MemoryStream tmpStream = new MemoryStream ();
2176 foreach (string key in data) {
2177 byte [] bytes = Encoding.UTF8.GetBytes (key);
2178 UrlEncodeAndWrite (tmpStream, bytes);
2179 tmpStream.WriteByte ((byte) '=');
2180 bytes = Encoding.UTF8.GetBytes (data [key]);
2181 UrlEncodeAndWrite (tmpStream, bytes);
2182 tmpStream.WriteByte ((byte) '&');
2185 token.ThrowIfCancellationRequested ();
2187 int length = (int) tmpStream.Length;
2189 tmpStream.SetLength (--length); // remove trailing '&'
2191 byte [] buf = tmpStream.GetBuffer ();
2192 request.ContentLength = length;
2193 using (Stream rqStream = await request.GetRequestStreamAsync ().ConfigureAwait (false)) {
2194 await rqStream.WriteAsync (buf, 0, length, token).ConfigureAwait (false);
2198 response = await GetWebResponseTaskAsync (request, token).ConfigureAwait (false);
2199 return await ReadAllTaskAsync (request, response, token).ConfigureAwait (false);
2201 if (response != null)