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 int socketBufferSize = 4096;
83 static readonly string urlEncodedCType = "application/x-www-form-urlencoded";
84 static byte [] hexBytes;
85 ICredentials credentials;
86 WebHeaderCollection headers;
87 WebHeaderCollection responseHeaders;
90 NameValueCollection queryString;
93 bool proxySet = false;
95 Encoding encoding = Encoding.Default;
97 // RequestCachePolicy cache_policy;
99 CancellationTokenSource cts;
105 hexBytes = new byte [16];
107 for (int i = '0'; i <= '9'; i++, index++)
108 hexBytes [index] = (byte) i;
110 for (int i = 'a'; i <= 'f'; i++, index++)
111 hexBytes [index] = (byte) i;
120 public string BaseAddress {
122 if (baseString == null) {
123 if (baseAddress == null)
127 baseString = baseAddress.ToString ();
132 if (value == null || value.Length == 0) {
135 baseAddress = new Uri (value);
140 static Exception GetMustImplement ()
142 return new NotImplementedException ();
145 [MonoTODO ("Value can be set but is currently ignored")]
146 public RequestCachePolicy CachePolicy
149 throw GetMustImplement ();
151 set { /*cache_policy = value;*/ }
154 [MonoTODO ("Value can be set but is ignored")]
155 public bool UseDefaultCredentials
158 throw GetMustImplement ();
161 // This makes no sense in mono
165 public ICredentials Credentials {
166 get { return credentials; }
167 set { credentials = value; }
170 public WebHeaderCollection Headers {
173 headers = new WebHeaderCollection ();
177 set { headers = value; }
180 public NameValueCollection QueryString {
182 if (queryString == null)
183 queryString = new NameValueCollection ();
187 set { queryString = value; }
190 public WebHeaderCollection ResponseHeaders {
191 get { return responseHeaders; }
194 public Encoding Encoding {
195 get { return encoding; }
198 throw new ArgumentNullException ("Encoding");
203 public IWebProxy Proxy {
206 return WebRequest.DefaultWebProxy;
219 return is_busy || (cts != null);
230 throw new NotSupportedException ("WebClient does not support concurrent I/O operations.");
243 public byte [] DownloadData (string address)
246 throw new ArgumentNullException ("address");
248 return DownloadData (CreateUri (address));
251 public byte [] DownloadData (Uri address)
254 throw new ArgumentNullException ("address");
259 return DownloadDataCore (address, null);
265 byte [] DownloadDataCore (Uri address, object userToken)
267 WebRequest request = null;
270 request = SetupRequest (address);
271 return ReadAll (request, userToken);
272 } catch (ThreadInterruptedException){
275 throw new WebException ("User canceled the request", WebExceptionStatus.RequestCanceled);
276 } catch (WebException) {
278 } catch (Exception ex) {
279 throw new WebException ("An error occurred performing a WebClient request.", ex);
285 public void DownloadFile (string address, string fileName)
288 throw new ArgumentNullException ("address");
290 DownloadFile (CreateUri (address), fileName);
293 public void DownloadFile (Uri address, string fileName)
296 throw new ArgumentNullException ("address");
297 if (fileName == null)
298 throw new ArgumentNullException ("fileName");
303 DownloadFileCore (address, fileName, null);
304 } catch (WebException) {
306 } catch (Exception ex) {
307 throw new WebException ("An error occurred " +
308 "performing a WebClient request.", ex);
314 void DownloadFileCore (Uri address, string fileName, object userToken)
316 WebRequest request = null;
318 using (FileStream f = new FileStream (fileName, FileMode.Create)) {
320 request = SetupRequest (address);
321 WebResponse response = GetWebResponse (request);
322 Stream st = response.GetResponseStream ();
324 int cLength = (int) response.ContentLength;
325 int length = (cLength <= -1 || cLength > 32*1024) ? 32*1024 : cLength;
326 byte [] buffer = new byte [length];
329 long notify_total = 0;
330 while ((nread = st.Read (buffer, 0, length)) != 0) {
331 notify_total += nread;
333 OnDownloadProgressChanged (
334 new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, userToken));
335 f.Write (buffer, 0, nread);
338 if (cLength > 0 && notify_total < cLength)
339 throw new WebException ("Download aborted prematurely.", WebExceptionStatus.ReceiveFailure);
340 } catch (ThreadInterruptedException){
350 public Stream OpenRead (string address)
353 throw new ArgumentNullException ("address");
354 return OpenRead (CreateUri (address));
357 public Stream OpenRead (Uri address)
360 throw new ArgumentNullException ("address");
362 WebRequest request = null;
366 request = SetupRequest (address);
367 WebResponse response = GetWebResponse (request);
368 return response.GetResponseStream ();
369 } catch (WebException) {
371 } catch (Exception ex) {
372 throw new WebException ("An error occurred " +
373 "performing a WebClient request.", ex);
381 public Stream OpenWrite (string address)
384 throw new ArgumentNullException ("address");
386 return OpenWrite (CreateUri (address));
389 public Stream OpenWrite (string address, string method)
392 throw new ArgumentNullException ("address");
394 return OpenWrite (CreateUri (address), method);
397 public Stream OpenWrite (Uri address)
399 return OpenWrite (address, (string) null);
402 public Stream OpenWrite (Uri address, string method)
405 throw new ArgumentNullException ("address");
410 WebRequest request = SetupRequest (address, method, true);
411 return request.GetRequestStream ();
412 } catch (WebException) {
414 } catch (Exception ex) {
415 throw new WebException ("An error occurred " +
416 "performing a WebClient request.", ex);
422 private string DetermineMethod (Uri address, string method, bool is_upload)
427 if (address.Scheme == Uri.UriSchemeFtp)
428 return (is_upload) ? "STOR" : "RETR";
430 return (is_upload) ? "POST" : "GET";
435 public byte [] UploadData (string address, byte [] data)
438 throw new ArgumentNullException ("address");
440 return UploadData (CreateUri (address), data);
443 public byte [] UploadData (string address, string method, byte [] data)
446 throw new ArgumentNullException ("address");
448 return UploadData (CreateUri (address), method, data);
451 public byte [] UploadData (Uri address, byte [] data)
453 return UploadData (address, (string) null, data);
456 public byte [] UploadData (Uri address, string method, byte [] data)
459 throw new ArgumentNullException ("address");
461 throw new ArgumentNullException ("data");
466 return UploadDataCore (address, method, data, null);
467 } catch (WebException) {
469 } catch (Exception ex) {
470 throw new WebException ("An error occurred " +
471 "performing a WebClient request.", ex);
477 byte [] UploadDataCore (Uri address, string method, byte [] data, object userToken)
479 WebRequest request = SetupRequest (address, method, true);
481 int contentLength = data.Length;
482 request.ContentLength = contentLength;
483 using (Stream stream = request.GetRequestStream ()) {
485 while (offset < contentLength) {
486 var size = Math.Min (contentLength - offset, socketBufferSize);
487 stream.Write (data, offset, size);
491 if (contentLength > 0)
492 percent = (int) ((long)offset * 100 / contentLength);
493 var args = new UploadProgressChangedEventArgs (0, 0, offset, contentLength, percent, userToken);
494 OnUploadProgressChanged (args);
498 return ReadAll (request, userToken);
499 } catch (ThreadInterruptedException){
508 public byte [] UploadFile (string address, string fileName)
511 throw new ArgumentNullException ("address");
513 return UploadFile (CreateUri (address), fileName);
516 public byte [] UploadFile (Uri address, string fileName)
518 return UploadFile (address, (string) null, fileName);
521 public byte [] UploadFile (string address, string method, string fileName)
523 return UploadFile (CreateUri (address), method, fileName);
526 public byte [] UploadFile (Uri address, string method, string fileName)
529 throw new ArgumentNullException ("address");
530 if (fileName == null)
531 throw new ArgumentNullException ("fileName");
536 return UploadFileCore (address, method, fileName, null);
537 } catch (WebException) {
539 } catch (Exception ex) {
540 throw new WebException ("An error occurred " +
541 "performing a WebClient request.", ex);
547 byte [] UploadFileCore (Uri address, string method, string fileName, object userToken)
549 string fileCType = Headers ["Content-Type"];
550 if (fileCType != null) {
551 string lower = fileCType.ToLower ();
552 if (lower.StartsWith ("multipart/"))
553 throw new WebException ("Content-Type cannot be set to a multipart" +
554 " type for this request.");
556 fileCType = "application/octet-stream";
559 bool needs_boundary = (method != "PUT"); // only verified case so far
560 string boundary = null;
561 if (needs_boundary) {
562 boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
563 Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
565 Stream reqStream = null;
566 Stream fStream = null;
567 byte [] resultBytes = null;
569 fileName = Path.GetFullPath (fileName);
571 WebRequest request = null;
573 fStream = File.OpenRead (fileName);
574 request = SetupRequest (address, method, true);
575 reqStream = request.GetRequestStream ();
576 byte [] bytes_boundary = null;
577 if (needs_boundary) {
578 bytes_boundary = Encoding.ASCII.GetBytes (boundary);
579 reqStream.WriteByte ((byte) '-');
580 reqStream.WriteByte ((byte) '-');
581 reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
582 reqStream.WriteByte ((byte) '\r');
583 reqStream.WriteByte ((byte) '\n');
584 string partHeaders = String.Format ("Content-Disposition: form-data; " +
585 "name=\"file\"; filename=\"{0}\"\r\n" +
586 "Content-Type: {1}\r\n\r\n",
587 Path.GetFileName (fileName), fileCType);
589 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
590 reqStream.Write (partHeadersBytes, 0, partHeadersBytes.Length);
595 long step = 16384; // every 16kB
596 if (fStream.CanSeek) {
597 file_size = fStream.Length;
598 step = file_size / 100;
600 var upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, 0, userToken);
601 OnUploadProgressChanged (upload_args);
602 byte [] buffer = new byte [4096];
604 while ((nread = fStream.Read (buffer, 0, 4096)) > 0) {
605 reqStream.Write (buffer, 0, nread);
608 if (sum >= step || nread < 4096) {
611 percent = (int) (bytes_sent * 100 / file_size);
612 upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, percent, userToken);
613 OnUploadProgressChanged (upload_args);
618 if (needs_boundary) {
619 reqStream.WriteByte ((byte) '\r');
620 reqStream.WriteByte ((byte) '\n');
621 reqStream.WriteByte ((byte) '-');
622 reqStream.WriteByte ((byte) '-');
623 reqStream.Write (bytes_boundary, 0, bytes_boundary.Length);
624 reqStream.WriteByte ((byte) '-');
625 reqStream.WriteByte ((byte) '-');
626 reqStream.WriteByte ((byte) '\r');
627 reqStream.WriteByte ((byte) '\n');
631 resultBytes = ReadAll (request, userToken);
632 } catch (ThreadInterruptedException){
640 if (reqStream != null)
647 public byte[] UploadValues (string address, NameValueCollection data)
650 throw new ArgumentNullException ("address");
652 return UploadValues (CreateUri (address), data);
655 public byte[] UploadValues (string address, string method, NameValueCollection data)
658 throw new ArgumentNullException ("address");
659 return UploadValues (CreateUri (address), method, data);
662 public byte[] UploadValues (Uri address, NameValueCollection data)
664 return UploadValues (address, (string) null, data);
667 public byte[] UploadValues (Uri address, string method, NameValueCollection data)
670 throw new ArgumentNullException ("address");
672 throw new ArgumentNullException ("data");
677 return UploadValuesCore (address, method, data, null);
678 } catch (WebException) {
680 } catch (Exception ex) {
681 throw new WebException ("An error occurred " +
682 "performing a WebClient request.", ex);
688 byte[] UploadValuesCore (Uri uri, string method, NameValueCollection data, object userToken)
690 string cType = Headers ["Content-Type"];
691 if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
692 throw new WebException ("Content-Type header cannot be changed from its default " +
693 "value for this request.");
695 Headers ["Content-Type"] = urlEncodedCType;
696 WebRequest request = SetupRequest (uri, method, true);
698 MemoryStream tmpStream = new MemoryStream ();
699 foreach (string key in data) {
700 byte [] bytes = Encoding.UTF8.GetBytes (key);
701 UrlEncodeAndWrite (tmpStream, bytes);
702 tmpStream.WriteByte ((byte) '=');
703 bytes = Encoding.UTF8.GetBytes (data [key]);
704 UrlEncodeAndWrite (tmpStream, bytes);
705 tmpStream.WriteByte ((byte) '&');
708 int length = (int) tmpStream.Length;
710 tmpStream.SetLength (--length); // remove trailing '&'
712 byte [] buf = tmpStream.GetBuffer ();
713 request.ContentLength = length;
714 using (Stream rqStream = request.GetRequestStream ()) {
715 rqStream.Write (buf, 0, length);
719 return ReadAll (request, userToken);
720 } catch (ThreadInterruptedException) {
726 public string DownloadString (string address)
729 throw new ArgumentNullException ("address");
731 return ConvertDataToString (DownloadData (CreateUri (address)));
734 public string DownloadString (Uri address)
737 throw new ArgumentNullException ("address");
739 return ConvertDataToString (DownloadData (CreateUri (address)));
742 string ConvertDataToString (byte[] data)
744 int preambleLength = 0;
745 var enc = GetEncodingFromBuffer (data, data.Length, ref preambleLength) ?? encoding;
746 return enc.GetString (data, preambleLength, data.Length - preambleLength);
749 internal static Encoding GetEncodingFromBuffer (byte[] buffer, int length, ref int preambleLength)
751 var encodings_with_preamble = new [] { Encoding.UTF8, Encoding.UTF32, Encoding.Unicode };
752 foreach (var enc in encodings_with_preamble) {
753 if ((preambleLength = StartsWith (buffer, length, enc.GetPreamble ())) > 0)
760 static int StartsWith (byte[] array, int length, byte[] value)
762 if (length < value.Length)
765 for (int i = 0; i < value.Length; ++i) {
766 if (array [i] != value [i])
773 public string UploadString (string address, string data)
776 throw new ArgumentNullException ("address");
778 throw new ArgumentNullException ("data");
780 byte [] resp = UploadData (address, encoding.GetBytes (data));
781 return encoding.GetString (resp);
784 public string UploadString (string address, string method, string data)
787 throw new ArgumentNullException ("address");
789 throw new ArgumentNullException ("data");
791 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
792 return encoding.GetString (resp);
795 public string UploadString (Uri address, string data)
798 throw new ArgumentNullException ("address");
800 throw new ArgumentNullException ("data");
802 byte [] resp = UploadData (address, encoding.GetBytes (data));
803 return encoding.GetString (resp);
806 public string UploadString (Uri address, string method, string data)
809 throw new ArgumentNullException ("address");
811 throw new ArgumentNullException ("data");
813 byte [] resp = UploadData (address, method, encoding.GetBytes (data));
814 return encoding.GetString (resp);
817 public event DownloadDataCompletedEventHandler DownloadDataCompleted;
818 public event AsyncCompletedEventHandler DownloadFileCompleted;
819 public event DownloadProgressChangedEventHandler DownloadProgressChanged;
820 public event DownloadStringCompletedEventHandler DownloadStringCompleted;
821 public event OpenReadCompletedEventHandler OpenReadCompleted;
822 public event OpenWriteCompletedEventHandler OpenWriteCompleted;
823 public event UploadDataCompletedEventHandler UploadDataCompleted;
824 public event UploadFileCompletedEventHandler UploadFileCompleted;
825 public event UploadProgressChangedEventHandler UploadProgressChanged;
826 public event UploadStringCompletedEventHandler UploadStringCompleted;
827 public event UploadValuesCompletedEventHandler UploadValuesCompleted;
829 Uri CreateUri (string address)
833 if (baseAddress == null)
834 uri = new Uri (address);
836 uri = new Uri (baseAddress, address);
837 return CreateUri (uri);
840 return new Uri (Path.GetFullPath (address));
843 Uri CreateUri (Uri address)
845 Uri result = address;
846 if (baseAddress != null && !result.IsAbsoluteUri) {
848 result = new Uri (baseAddress, result.OriginalString);
850 return result; // Not much we can do here.
854 string query = result.Query;
855 if (String.IsNullOrEmpty (query))
856 query = GetQueryString (true);
857 UriBuilder builder = new UriBuilder (address);
858 if (!String.IsNullOrEmpty (query))
859 builder.Query = query.Substring (1);
863 string GetQueryString (bool add_qmark)
865 if (queryString == null || queryString.Count == 0)
868 StringBuilder sb = new StringBuilder ();
872 foreach (string key in queryString)
873 sb.AppendFormat ("{0}={1}&", key, UrlEncode (queryString [key]));
876 sb.Length--; // removes last '&' or the '?' if empty.
881 return sb.ToString ();
884 WebRequest SetupRequest (Uri uri)
886 WebRequest request = GetWebRequest (uri);
888 request.Proxy = Proxy;
889 if (credentials != null)
890 request.Credentials = credentials;
891 else if (!String.IsNullOrEmpty (uri.UserInfo)) {
892 // Perhaps this should be done by the underlying URI handler?
893 ICredentials creds = GetCredentials (uri.UserInfo);
895 request.Credentials = creds;
898 // Special headers. These are properties of HttpWebRequest.
899 // What do we do with other requests differnt from HttpWebRequest?
900 if (headers != null && headers.Count != 0 && (request is HttpWebRequest)) {
901 HttpWebRequest req = (HttpWebRequest) request;
902 string expect = headers ["Expect"];
903 string contentType = headers ["Content-Type"];
904 string accept = headers ["Accept"];
905 string connection = headers ["Connection"];
906 string userAgent = headers ["User-Agent"];
907 string referer = headers ["Referer"];
908 headers.RemoveInternal ("Expect");
909 headers.RemoveInternal ("Content-Type");
910 headers.RemoveInternal ("Accept");
911 headers.RemoveInternal ("Connection");
912 headers.RemoveInternal ("Referer");
913 headers.RemoveInternal ("User-Agent");
914 request.Headers = headers;
916 if (expect != null && expect.Length > 0)
919 if (accept != null && accept.Length > 0)
922 if (contentType != null && contentType.Length > 0)
923 req.ContentType = contentType;
925 if (connection != null && connection.Length > 0)
926 req.Connection = connection;
928 if (userAgent != null && userAgent.Length > 0)
929 req.UserAgent = userAgent;
931 if (referer != null && referer.Length > 0)
932 req.Referer = referer;
935 responseHeaders = null;
939 WebRequest SetupRequest (Uri uri, string method, bool is_upload)
941 WebRequest request = SetupRequest (uri);
942 request.Method = DetermineMethod (uri, method, is_upload);
946 static NetworkCredential GetCredentials (string user_info)
948 string [] creds = user_info.Split (':');
949 if (creds.Length != 2)
952 if (creds [0].IndexOf ('\\') != -1) {
953 string [] user = creds [0].Split ('\\');
954 if (user.Length != 2)
956 return new NetworkCredential (user [1], creds [1], user [0]);
958 return new NetworkCredential (creds [0], creds [1]);
961 byte [] ReadAll (WebRequest request, object userToken)
963 WebResponse response = GetWebResponse (request);
964 Stream stream = response.GetResponseStream ();
965 int length = (int) response.ContentLength;
966 HttpWebRequest wreq = request as HttpWebRequest;
968 if (length > -1 && wreq != null && (int) wreq.AutomaticDecompression != 0) {
969 string content_encoding = ((HttpWebResponse) response).ContentEncoding;
970 if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
971 ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
975 MemoryStream ms = null;
976 bool nolength = (length == -1);
977 int size = ((nolength) ? 8192 : length);
979 ms = new MemoryStream ();
984 byte [] buffer = new byte [size];
985 while ((nread = stream.Read (buffer, offset, size)) != 0) {
987 ms.Write (buffer, 0, nread);
994 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, userToken));
999 return ms.ToArray ();
1004 string UrlEncode (string str)
1006 StringBuilder result = new StringBuilder ();
1008 int len = str.Length;
1009 for (int i = 0; i < len; i++) {
1012 result.Append ('+');
1013 else if ((c < '0' && c != '-' && c != '.') ||
1014 (c < 'A' && c > '9') ||
1015 (c > 'Z' && c < 'a' && c != '_') ||
1017 result.Append ('%');
1018 int idx = ((int) c) >> 4;
1019 result.Append ((char) hexBytes [idx]);
1020 idx = ((int) c) & 0x0F;
1021 result.Append ((char) hexBytes [idx]);
1027 return result.ToString ();
1030 static void UrlEncodeAndWrite (Stream stream, byte [] bytes)
1035 int len = bytes.Length;
1039 for (int i = 0; i < len; i++) {
1040 char c = (char) bytes [i];
1042 stream.WriteByte ((byte) '+');
1043 else if ((c < '0' && c != '-' && c != '.') ||
1044 (c < 'A' && c > '9') ||
1045 (c > 'Z' && c < 'a' && c != '_') ||
1047 stream.WriteByte ((byte) '%');
1048 int idx = ((int) c) >> 4;
1049 stream.WriteByte (hexBytes [idx]);
1050 idx = ((int) c) & 0x0F;
1051 stream.WriteByte (hexBytes [idx]);
1053 stream.WriteByte ((byte) c);
1058 public void CancelAsync ()
1068 if (async_thread == null)
1072 // We first flag things as done, in case the Interrupt hangs
1073 // or the thread decides to hang in some other way inside the
1074 // event handlers, or if we are stuck somewhere else. This
1075 // ensures that the WebClient object is reusable immediately
1077 Thread t = async_thread;
1083 void CompleteAsync ()
1087 async_thread = null;
1096 // DownloadDataAsync
1098 public void DownloadDataAsync (Uri address)
1100 DownloadDataAsync (address, null);
1103 public void DownloadDataAsync (Uri address, object userToken)
1105 if (address == null)
1106 throw new ArgumentNullException ("address");
1112 async_thread = new Thread (delegate (object state) {
1113 object [] args = (object []) state;
1115 byte [] data = DownloadDataCore ((Uri) args [0], args [1]);
1116 OnDownloadDataCompleted (
1117 new DownloadDataCompletedEventArgs (data, null, false, args [1]));
1118 } catch (Exception e){
1119 bool canceled = false;
1120 WebException we = e as WebException;
1122 canceled = we.Status == WebExceptionStatus.RequestCanceled;
1123 OnDownloadDataCompleted (
1124 new DownloadDataCompletedEventArgs (null, e, canceled, args [1]));
1127 object [] cb_args = new object [] { CreateUri (address), userToken };
1128 async_thread.IsBackground = true;
1129 async_thread.Start (cb_args);
1133 // DownloadFileAsync
1135 public void DownloadFileAsync (Uri address, string fileName)
1137 DownloadFileAsync (address, fileName, null);
1140 public void DownloadFileAsync (Uri address, string fileName, object userToken)
1142 if (address == null)
1143 throw new ArgumentNullException ("address");
1144 if (fileName == null)
1145 throw new ArgumentNullException ("fileName");
1151 async_thread = new Thread (delegate (object state) {
1152 object [] args = (object []) state;
1154 DownloadFileCore ((Uri) args [0], (string) args [1], args [2]);
1155 OnDownloadFileCompleted (
1156 new AsyncCompletedEventArgs (null, false, args [2]));
1157 } catch (ThreadInterruptedException){
1158 OnDownloadFileCompleted (
1159 new AsyncCompletedEventArgs (null, true, args [2]));
1160 } catch (Exception e){
1161 OnDownloadFileCompleted (
1162 new AsyncCompletedEventArgs (e, false, args [2]));
1164 object [] cb_args = new object [] { CreateUri (address), fileName, userToken };
1165 async_thread.IsBackground = true;
1166 async_thread.Start (cb_args);
1170 // DownloadStringAsync
1172 public void DownloadStringAsync (Uri address)
1174 DownloadStringAsync (address, null);
1177 public void DownloadStringAsync (Uri address, object userToken)
1179 if (address == null)
1180 throw new ArgumentNullException ("address");
1186 async_thread = new Thread (delegate (object state) {
1187 object [] args = (object []) state;
1189 string data = ConvertDataToString (DownloadDataCore ((Uri) args [0], args [1]));
1190 OnDownloadStringCompleted (
1191 new DownloadStringCompletedEventArgs (data, null, false, args [1]));
1192 } catch (Exception e){
1193 bool canceled = false;
1194 WebException we = e as WebException;
1196 canceled = we.Status == WebExceptionStatus.RequestCanceled;
1197 OnDownloadStringCompleted (
1198 new DownloadStringCompletedEventArgs (null, e, canceled, args [1]));
1200 object [] cb_args = new object [] { CreateUri (address), userToken };
1201 async_thread.IsBackground = true;
1202 async_thread.Start (cb_args);
1208 public void OpenReadAsync (Uri address)
1210 OpenReadAsync (address, null);
1213 public void OpenReadAsync (Uri address, 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]);
1227 WebResponse response = GetWebResponse (request);
1228 Stream stream = response.GetResponseStream ();
1229 OnOpenReadCompleted (
1230 new OpenReadCompletedEventArgs (stream, null, false, args [1]));
1231 } catch (ThreadInterruptedException){
1232 if (request != null)
1235 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, args [1]));
1236 } catch (Exception e){
1237 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, e, false, args [1]));
1239 object [] cb_args = new object [] { CreateUri (address), userToken };
1240 async_thread.IsBackground = true;
1241 async_thread.Start (cb_args);
1247 public void OpenWriteAsync (Uri address)
1249 OpenWriteAsync (address, null);
1252 public void OpenWriteAsync (Uri address, string method)
1254 OpenWriteAsync (address, method, null);
1257 public void OpenWriteAsync (Uri address, string method, object userToken)
1259 if (address == null)
1260 throw new ArgumentNullException ("address");
1266 async_thread = new Thread (delegate (object state) {
1267 object [] args = (object []) state;
1268 WebRequest request = null;
1270 request = SetupRequest ((Uri) args [0], (string) args [1], true);
1271 Stream stream = request.GetRequestStream ();
1272 OnOpenWriteCompleted (
1273 new OpenWriteCompletedEventArgs (stream, null, false, args [2]));
1274 } catch (ThreadInterruptedException){
1275 if (request != null)
1277 OnOpenWriteCompleted (
1278 new OpenWriteCompletedEventArgs (null, null, true, args [2]));
1279 } catch (Exception e){
1280 OnOpenWriteCompleted (
1281 new OpenWriteCompletedEventArgs (null, e, false, args [2]));
1283 object [] cb_args = new object [] { CreateUri (address), method, userToken };
1284 async_thread.IsBackground = true;
1285 async_thread.Start (cb_args);
1291 public void UploadDataAsync (Uri address, byte [] data)
1293 UploadDataAsync (address, null, data);
1296 public void UploadDataAsync (Uri address, string method, byte [] data)
1298 UploadDataAsync (address, method, data, null);
1301 public void UploadDataAsync (Uri address, string method, byte [] data, object userToken)
1303 if (address == null)
1304 throw new ArgumentNullException ("address");
1306 throw new ArgumentNullException ("data");
1312 async_thread = new Thread (delegate (object state) {
1313 object [] args = (object []) state;
1317 data2 = UploadDataCore ((Uri) args [0], (string) args [1], (byte []) args [2], args [3]);
1319 OnUploadDataCompleted (
1320 new UploadDataCompletedEventArgs (data2, null, false, args [3]));
1321 } catch (ThreadInterruptedException){
1322 OnUploadDataCompleted (
1323 new UploadDataCompletedEventArgs (null, null, true, args [3]));
1324 } catch (Exception e){
1325 OnUploadDataCompleted (
1326 new UploadDataCompletedEventArgs (null, e, false, args [3]));
1328 object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
1329 async_thread.IsBackground = true;
1330 async_thread.Start (cb_args);
1336 public void UploadFileAsync (Uri address, string fileName)
1338 UploadFileAsync (address, null, fileName);
1341 public void UploadFileAsync (Uri address, string method, string fileName)
1343 UploadFileAsync (address, method, fileName, null);
1346 public void UploadFileAsync (Uri address, string method, string fileName, object userToken)
1348 if (address == null)
1349 throw new ArgumentNullException ("address");
1350 if (fileName == null)
1351 throw new ArgumentNullException ("fileName");
1357 async_thread = new Thread (delegate (object state) {
1358 object [] args = (object []) state;
1362 data = UploadFileCore ((Uri) args [0], (string) args [1], (string) args [2], args [3]);
1363 OnUploadFileCompleted (
1364 new UploadFileCompletedEventArgs (data, null, false, args [3]));
1365 } catch (ThreadInterruptedException){
1366 OnUploadFileCompleted (
1367 new UploadFileCompletedEventArgs (null, null, true, args [3]));
1368 } catch (Exception e){
1369 OnUploadFileCompleted (
1370 new UploadFileCompletedEventArgs (null, e, false, args [3]));
1372 object [] cb_args = new object [] { CreateUri (address), method, fileName, userToken };
1373 async_thread.IsBackground = true;
1374 async_thread.Start (cb_args);
1378 // UploadStringAsync
1380 public void UploadStringAsync (Uri address, string data)
1382 UploadStringAsync (address, null, data);
1385 public void UploadStringAsync (Uri address, string method, string data)
1387 UploadStringAsync (address, method, data, null);
1390 public void UploadStringAsync (Uri address, string method, string data, object userToken)
1392 if (address == null)
1393 throw new ArgumentNullException ("address");
1395 throw new ArgumentNullException ("data");
1401 async_thread = new Thread (delegate (object state) {
1402 object [] args = (object []) state;
1405 string data2 = UploadString ((Uri) args [0], (string) args [1], (string) args [2]);
1406 OnUploadStringCompleted (
1407 new UploadStringCompletedEventArgs (data2, null, false, args [3]));
1408 } catch (Exception e){
1409 if (e is ThreadInterruptedException || e.InnerException is ThreadInterruptedException) {
1410 OnUploadStringCompleted (
1411 new UploadStringCompletedEventArgs (null, null, true, args [3]));
1414 OnUploadStringCompleted (
1415 new UploadStringCompletedEventArgs (null, e, false, args [3]));
1417 object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
1418 async_thread.IsBackground = true;
1419 async_thread.Start (cb_args);
1423 // UploadValuesAsync
1425 public void UploadValuesAsync (Uri address, NameValueCollection data)
1427 UploadValuesAsync (address, null, data);
1430 public void UploadValuesAsync (Uri address, string method, NameValueCollection data)
1432 UploadValuesAsync (address, method, data, null);
1435 public void UploadValuesAsync (Uri address, string method, NameValueCollection data, object userToken)
1437 if (address == null)
1438 throw new ArgumentNullException ("address");
1440 throw new ArgumentNullException ("data");
1446 async_thread = new Thread (delegate (object state) {
1447 object [] args = (object []) state;
1449 byte [] values = UploadValuesCore ((Uri) args [0], (string) args [1], (NameValueCollection) args [2], args [3]);
1450 OnUploadValuesCompleted (
1451 new UploadValuesCompletedEventArgs (values, null, false, args [3]));
1452 } catch (ThreadInterruptedException){
1453 OnUploadValuesCompleted (
1454 new UploadValuesCompletedEventArgs (null, null, true, args [3]));
1455 } catch (Exception e){
1456 OnUploadValuesCompleted (
1457 new UploadValuesCompletedEventArgs (null, e, false, args [3]));
1459 object [] cb_args = new object [] { CreateUri (address), method, data, userToken };
1460 async_thread.IsBackground = true;
1461 async_thread.Start (cb_args);
1465 protected virtual void OnDownloadDataCompleted (DownloadDataCompletedEventArgs e)
1468 if (DownloadDataCompleted != null)
1469 DownloadDataCompleted (this, e);
1472 protected virtual void OnDownloadFileCompleted (AsyncCompletedEventArgs e)
1475 if (DownloadFileCompleted != null)
1476 DownloadFileCompleted (this, e);
1479 protected virtual void OnDownloadProgressChanged (DownloadProgressChangedEventArgs e)
1481 if (DownloadProgressChanged != null)
1482 DownloadProgressChanged (this, e);
1485 protected virtual void OnDownloadStringCompleted (DownloadStringCompletedEventArgs e)
1488 if (DownloadStringCompleted != null)
1489 DownloadStringCompleted (this, e);
1492 protected virtual void OnOpenReadCompleted (OpenReadCompletedEventArgs e)
1495 if (OpenReadCompleted != null)
1496 OpenReadCompleted (this, e);
1499 protected virtual void OnOpenWriteCompleted (OpenWriteCompletedEventArgs e)
1502 if (OpenWriteCompleted != null)
1503 OpenWriteCompleted (this, e);
1506 protected virtual void OnUploadDataCompleted (UploadDataCompletedEventArgs e)
1509 if (UploadDataCompleted != null)
1510 UploadDataCompleted (this, e);
1513 protected virtual void OnUploadFileCompleted (UploadFileCompletedEventArgs e)
1516 if (UploadFileCompleted != null)
1517 UploadFileCompleted (this, e);
1520 protected virtual void OnUploadProgressChanged (UploadProgressChangedEventArgs e)
1522 if (UploadProgressChanged != null)
1523 UploadProgressChanged (this, e);
1526 protected virtual void OnUploadStringCompleted (UploadStringCompletedEventArgs e)
1529 if (UploadStringCompleted != null)
1530 UploadStringCompleted (this, e);
1533 protected virtual void OnUploadValuesCompleted (UploadValuesCompletedEventArgs e)
1536 if (UploadValuesCompleted != null)
1537 UploadValuesCompleted (this, e);
1540 protected virtual WebResponse GetWebResponse (WebRequest request, IAsyncResult result)
1542 WebResponse response = request.EndGetResponse (result);
1543 responseHeaders = response.Headers;
1547 protected virtual WebRequest GetWebRequest (Uri address)
1549 return WebRequest.Create (address);
1552 protected virtual WebResponse GetWebResponse (WebRequest request)
1554 WebResponse response = request.GetResponse ();
1555 responseHeaders = response.Headers;
1561 // DownloadDataTaskAsync
1563 public Task<byte[]> DownloadDataTaskAsync (string address)
1565 return DownloadDataTaskAsync (CreateUri (address));
1568 public async Task<byte[]> DownloadDataTaskAsync (Uri address)
1570 WebRequest request = null;
1571 WebResponse response = null;
1574 cts = new CancellationTokenSource ();
1575 request = await SetupRequestAsync (address);
1576 response = await GetWebResponseTaskAsync (request, cts.Token);
1577 var result = await ReadAllTaskAsync (request, response, cts.Token);
1579 // Has to run on original context
1580 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (result, null, false, null));
1582 } catch (WebException ex) {
1583 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, false, null));
1585 } catch (OperationCanceledException) {
1586 if (request != null)
1588 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, null, true, null));
1590 } catch (Exception ex) {
1591 OnDownloadDataCompleted (new DownloadDataCompletedEventArgs (null, ex, true, null));
1592 throw new WebException ("An error occurred performing a WebClient request.", ex);
1594 if (response != null)
1599 Task<WebRequest> SetupRequestAsync (Uri address)
1601 return Task.Factory.StartNew (() => SetupRequest (address));
1604 async Task<WebRequest> SetupRequestAsync (Uri address, string method, bool is_upload)
1606 WebRequest request = await SetupRequestAsync (address).ConfigureAwait (false);
1607 request.Method = DetermineMethod (address, method, is_upload);
1611 async Task<WebResponse> GetWebResponseTaskAsync (WebRequest request, CancellationToken token)
1613 token.ThrowIfCancellationRequested ();
1614 WebResponse response = await request.GetResponseAsync ().ConfigureAwait (false);
1615 token.ThrowIfCancellationRequested ();
1616 responseHeaders = response.Headers;
1620 async Task<byte[]> ReadAllTaskAsync (WebRequest request, WebResponse response, CancellationToken token)
1622 Stream stream = response.GetResponseStream ();
1623 int length = (int)response.ContentLength;
1624 HttpWebRequest wreq = request as HttpWebRequest;
1626 if (length > -1 && wreq != null && (int)wreq.AutomaticDecompression != 0) {
1627 string content_encoding = ((HttpWebResponse)response).ContentEncoding;
1628 if (((content_encoding == "gzip" && (wreq.AutomaticDecompression & DecompressionMethods.GZip) != 0)) ||
1629 ((content_encoding == "deflate" && (wreq.AutomaticDecompression & DecompressionMethods.Deflate) != 0)))
1633 MemoryStream ms = null;
1634 bool nolength = (length == -1);
1635 int size = ((nolength) ? 8192 : length);
1637 ms = new MemoryStream ();
1642 byte [] buffer = new byte [size];
1643 token.ThrowIfCancellationRequested ();
1644 while ((nread = await stream.ReadAsync (buffer, offset, size, token)) != 0) {
1646 ms.Write (buffer, 0, nread);
1652 OnDownloadProgressChanged (new DownloadProgressChangedEventArgs (total, length, null));
1653 token.ThrowIfCancellationRequested ();
1656 return nolength ? ms.ToArray () : buffer;
1659 // DownloadFileTaskAsync
1661 public Task DownloadFileTaskAsync (string address, string fileName)
1663 if (address == null)
1664 throw new ArgumentNullException ("address");
1666 return DownloadFileTaskAsync (CreateUri (address), fileName);
1669 public async Task DownloadFileTaskAsync (Uri address, string fileName)
1671 if (address == null)
1672 throw new ArgumentNullException ("address");
1673 if (fileName == null)
1674 throw new ArgumentNullException ("fileName");
1676 WebRequest request = null;
1677 WebResponse response = null;
1681 cts = new CancellationTokenSource ();
1682 request = await SetupRequestAsync (address);
1683 response = await GetWebResponseTaskAsync (request, cts.Token);
1684 await DownloadFileTaskAsyncCore (request, response, fileName, cts.Token);
1685 OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, false, null));
1686 } catch (WebException ex) {
1687 OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
1689 } catch (OperationCanceledException) {
1690 if (request != null)
1692 OnDownloadFileCompleted (new AsyncCompletedEventArgs (null, true, null));
1694 } catch (Exception ex) {
1695 OnDownloadFileCompleted (new AsyncCompletedEventArgs (ex, false, null));
1696 throw new WebException ("An error occurred " +
1697 "performing a WebClient request.", ex);
1699 if (response != null)
1704 async Task DownloadFileTaskAsyncCore (WebRequest request, WebResponse response,
1705 string fileName, CancellationToken token)
1707 using (FileStream f = new FileStream (fileName, FileMode.Create)) {
1708 Stream st = response.GetResponseStream ();
1710 int cLength = (int)response.ContentLength;
1711 int length = (cLength <= -1 || cLength > 32 * 1024) ? 32 * 1024 : cLength;
1712 byte [] buffer = new byte [length];
1715 long notify_total = 0;
1716 token.ThrowIfCancellationRequested ();
1717 while ((nread = await st.ReadAsync (buffer, 0, length, token)) != 0) {
1718 notify_total += nread;
1719 OnDownloadProgressChanged (
1720 new DownloadProgressChangedEventArgs (notify_total, response.ContentLength, null));
1721 token.ThrowIfCancellationRequested ();
1722 await f.WriteAsync (buffer, 0, nread, token);
1723 token.ThrowIfCancellationRequested ();
1728 // OpenReadTaskAsync
1730 public Task<Stream> OpenReadTaskAsync (string address)
1732 if (address == null)
1733 throw new ArgumentNullException ("address");
1734 return OpenReadTaskAsync (CreateUri (address));
1737 public async Task<Stream> OpenReadTaskAsync (Uri address)
1739 if (address == null)
1740 throw new ArgumentNullException ("address");
1742 WebRequest request = null;
1745 cts = new CancellationTokenSource ();
1746 request = await SetupRequestAsync (address);
1747 WebResponse response = await GetWebResponseTaskAsync (request, cts.Token);
1748 var result = response.GetResponseStream ();
1749 cts.Token.ThrowIfCancellationRequested ();
1750 OnOpenReadCompleted (new OpenReadCompletedEventArgs (result, null, false, null));
1752 } catch (WebException ex) {
1753 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
1755 } catch (OperationCanceledException) {
1756 if (request != null)
1758 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, null, true, null));
1760 } catch (Exception ex) {
1761 OnOpenReadCompleted (new OpenReadCompletedEventArgs (null, ex, false, null));
1762 throw new WebException ("An error occurred " +
1763 "performing a WebClient request.", ex);
1767 // DownloadStringTaskAsync
1769 public Task<string> DownloadStringTaskAsync (string address)
1771 if (address == null)
1772 throw new ArgumentNullException ("address");
1774 return DownloadStringTaskAsync (CreateUri (address));
1777 public async Task<string> DownloadStringTaskAsync (Uri address)
1779 if (address == null)
1780 throw new ArgumentNullException ("address");
1782 WebRequest request = null;
1783 WebResponse response = null;
1787 cts = new CancellationTokenSource ();
1788 request = await SetupRequestAsync (address);
1789 response = await GetWebResponseTaskAsync (request, cts.Token);
1790 var data = await ReadAllTaskAsync (request, response, cts.Token);
1791 cts.Token.ThrowIfCancellationRequested ();
1792 var text = ConvertDataToString (data);
1793 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (text, null, false, null));
1795 } catch (WebException ex) {
1796 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, ex, false, null));
1798 } catch (OperationCanceledException) {
1799 if (request != null)
1801 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, null, true, null));
1803 } catch (Exception ex) {
1804 OnDownloadStringCompleted (new DownloadStringCompletedEventArgs (null, ex, true, null));
1805 throw new WebException ("An error occurred performing a WebClient request.", ex);
1807 if (response != null)
1812 // OpenWriteTaskAsync
1814 public Task<Stream> OpenWriteTaskAsync (string address)
1816 if (address == null)
1817 throw new ArgumentNullException ("address");
1819 return OpenWriteTaskAsync (CreateUri (address));
1822 public Task<Stream> OpenWriteTaskAsync (string address, string method)
1824 if (address == null)
1825 throw new ArgumentNullException ("address");
1827 return OpenWriteTaskAsync (CreateUri (address), method);
1830 public Task<Stream> OpenWriteTaskAsync (Uri address)
1832 return OpenWriteTaskAsync (address, (string) null);
1835 public async Task<Stream> OpenWriteTaskAsync (Uri address, string method)
1837 if (address == null)
1838 throw new ArgumentNullException ("address");
1840 WebRequest request = null;
1843 cts = new CancellationTokenSource ();
1844 request = SetupRequest (address);
1845 return await request.GetRequestStreamAsync ().ConfigureAwait (false);
1846 } catch (WebException) {
1848 } catch (OperationCanceledException) {
1849 if (request != null)
1852 } catch (Exception ex) {
1853 throw new WebException ("An error occurred " +
1854 "performing a WebClient request.", ex);
1860 // UploadDataTaskAsync
1862 public Task<byte[]> UploadDataTaskAsync (string address, byte [] data)
1864 if (address == null)
1865 throw new ArgumentNullException ("address");
1867 return UploadDataTaskAsync (CreateUri (address), data);
1870 public Task<byte[]> UploadDataTaskAsync (string address, string method, byte [] data)
1872 if (address == null)
1873 throw new ArgumentNullException ("address");
1875 return UploadDataTaskAsync (CreateUri (address), method, data);
1878 public Task<byte[]> UploadDataTaskAsync (Uri address, byte [] data)
1880 return UploadDataTaskAsync (address, (string) null, data);
1883 public async Task<byte[]> UploadDataTaskAsync (Uri address, string method, byte [] data)
1885 if (address == null)
1886 throw new ArgumentNullException ("address");
1888 throw new ArgumentNullException ("data");
1890 WebRequest request = null;
1893 cts = new CancellationTokenSource ();
1894 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
1895 var result = await UploadDataTaskAsyncCore (request, data, cts.Token).ConfigureAwait (false);
1896 OnUploadDataCompleted (new UploadDataCompletedEventArgs (result, null, false, null));
1898 } catch (WebException ex) {
1899 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, ex, false, null));
1901 } catch (OperationCanceledException) {
1902 if (request != null)
1904 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, null, true, null));
1906 } catch (Exception ex) {
1907 OnUploadDataCompleted (new UploadDataCompletedEventArgs (null, ex, true, null));
1908 throw new WebException ("An error occurred performing a WebClient request.", ex);
1912 async Task<byte[]> UploadDataTaskAsyncCore (WebRequest request, byte[] data, CancellationToken token)
1914 token.ThrowIfCancellationRequested ();
1916 int contentLength = data.Length;
1917 request.ContentLength = contentLength;
1918 using (Stream stream = await request.GetRequestStreamAsync ().ConfigureAwait (false)) {
1919 token.ThrowIfCancellationRequested ();
1920 await stream.WriteAsync (data, 0, contentLength, token).ConfigureAwait (false);
1921 token.ThrowIfCancellationRequested ();
1924 WebResponse response = null;
1927 response = await GetWebResponseTaskAsync (request, token).ConfigureAwait (false);
1928 return await ReadAllTaskAsync (request, response, token).ConfigureAwait (false);
1930 if (response != null)
1935 // UploadFileTaskAsync
1937 public Task<byte[]> UploadFileTaskAsync (string address, string fileName)
1939 if (address == null)
1940 throw new ArgumentNullException ("address");
1942 return UploadFileTaskAsync (CreateUri (address), fileName);
1945 public Task<byte[]> UploadFileTaskAsync (Uri address, string fileName)
1947 return UploadFileTaskAsync (address, (string) null, fileName);
1950 public Task<byte[]> UploadFileTaskAsync (string address, string method, string fileName)
1952 return UploadFileTaskAsync (CreateUri (address), method, fileName);
1955 public async Task<byte[]> UploadFileTaskAsync (Uri address, string method, string fileName)
1957 if (address == null)
1958 throw new ArgumentNullException ("address");
1959 if (fileName == null)
1960 throw new ArgumentNullException ("fileName");
1962 WebRequest request = null;
1965 cts = new CancellationTokenSource ();
1966 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
1967 var result = await UploadFileTaskAsyncCore (request, method, fileName, cts.Token).ConfigureAwait (false);
1968 OnUploadFileCompleted (new UploadFileCompletedEventArgs (result, null, false, null));
1970 } catch (WebException ex) {
1971 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, false, null));
1973 } catch (OperationCanceledException) {
1974 if (request != null)
1976 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, null, true, null));
1978 } catch (Exception ex) {
1979 OnUploadFileCompleted (new UploadFileCompletedEventArgs (null, ex, true, null));
1980 throw new WebException ("An error occurred performing a WebClient request.", ex);
1984 async Task<byte[]> UploadFileTaskAsyncCore (WebRequest request, string method,
1985 string fileName, CancellationToken token)
1987 token.ThrowIfCancellationRequested ();
1989 string fileCType = Headers ["Content-Type"];
1990 if (fileCType != null) {
1991 string lower = fileCType.ToLower ();
1992 if (lower.StartsWith ("multipart/"))
1993 throw new WebException ("Content-Type cannot be set to a multipart" +
1994 " type for this request.");
1996 fileCType = "application/octet-stream";
1999 bool needs_boundary = (method != "PUT"); // only verified case so far
2000 string boundary = null;
2001 if (needs_boundary) {
2002 boundary = "------------" + DateTime.Now.Ticks.ToString ("x");
2003 Headers ["Content-Type"] = String.Format ("multipart/form-data; boundary={0}", boundary);
2005 Stream reqStream = null;
2006 Stream fStream = null;
2007 WebResponse response = null;
2009 fileName = Path.GetFullPath (fileName);
2012 fStream = File.OpenRead (fileName);
2013 token.ThrowIfCancellationRequested ();
2014 reqStream = await request.GetRequestStreamAsync ().ConfigureAwait (false);
2015 token.ThrowIfCancellationRequested ();
2016 byte [] bytes_boundary = null;
2017 if (needs_boundary) {
2018 bytes_boundary = Encoding.ASCII.GetBytes (boundary);
2019 using (MemoryStream ms = new MemoryStream ()) {
2020 ms.WriteByte ((byte) '-');
2021 ms.WriteByte ((byte) '-');
2022 ms.Write (bytes_boundary, 0, bytes_boundary.Length);
2023 ms.WriteByte ((byte) '\r');
2024 ms.WriteByte ((byte) '\n');
2025 string partHeaders = String.Format (
2026 "Content-Disposition: form-data; " +
2027 "name=\"file\"; filename=\"{0}\"\r\n" +
2028 "Content-Type: {1}\r\n\r\n",
2029 Path.GetFileName (fileName), fileCType);
2030 byte [] partHeadersBytes = Encoding.UTF8.GetBytes (partHeaders);
2031 ms.Write (partHeadersBytes, 0, partHeadersBytes.Length);
2032 await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
2036 long bytes_sent = 0;
2037 long file_size = -1;
2038 long step = 16384; // every 16kB
2039 if (fStream.CanSeek) {
2040 file_size = fStream.Length;
2041 step = file_size / 100;
2043 var upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, 0, null);
2044 OnUploadProgressChanged (upload_args);
2045 byte [] buffer = new byte [4096];
2047 token.ThrowIfCancellationRequested ();
2048 while ((nread = await fStream.ReadAsync (buffer, 0, 4096, token).ConfigureAwait (false)) > 0) {
2049 token.ThrowIfCancellationRequested ();
2050 await reqStream.WriteAsync (buffer, 0, nread, token).ConfigureAwait (false);
2051 bytes_sent += nread;
2053 if (sum >= step || nread < 4096) {
2056 percent = (int) (bytes_sent * 100 / file_size);
2057 upload_args = new UploadProgressChangedEventArgs (0, 0, bytes_sent, file_size, percent, null);
2058 OnUploadProgressChanged (upload_args);
2063 if (needs_boundary) {
2064 using (MemoryStream ms = new MemoryStream ()) {
2065 ms.WriteByte ((byte) '\r');
2066 ms.WriteByte ((byte) '\n');
2067 ms.WriteByte ((byte) '-');
2068 ms.WriteByte ((byte) '-');
2069 ms.Write (bytes_boundary, 0, bytes_boundary.Length);
2070 ms.WriteByte ((byte) '-');
2071 ms.WriteByte ((byte) '-');
2072 ms.WriteByte ((byte) '\r');
2073 ms.WriteByte ((byte) '\n');
2074 await ms.CopyToAsync (reqStream, (int)ms.Position, token).ConfigureAwait (false);
2080 response = await GetWebResponseTaskAsync (request, token).ConfigureAwait (false);
2081 return await ReadAllTaskAsync (request, response, token).ConfigureAwait (false);
2083 if (fStream != null)
2086 if (reqStream != null)
2089 if (response != null)
2094 // UploadStringTaskAsync
2096 public Task<string> UploadStringTaskAsync (string address, string data)
2098 if (address == null)
2099 throw new ArgumentNullException ("address");
2101 throw new ArgumentNullException ("data");
2103 return UploadStringTaskAsync (CreateUri (address), null, data);
2106 public Task<string> UploadStringTaskAsync (string address, string method, string data)
2108 if (address == null)
2109 throw new ArgumentNullException ("address");
2111 throw new ArgumentNullException ("data");
2113 return UploadStringTaskAsync (CreateUri (address), method, data);
2116 public Task<string> UploadStringTaskAsync (Uri address, string data)
2118 if (address == null)
2119 throw new ArgumentNullException ("address");
2121 throw new ArgumentNullException ("data");
2123 return UploadStringTaskAsync (address, null, data);
2126 public async Task<string> UploadStringTaskAsync (Uri address, string method, string data)
2128 if (address == null)
2129 throw new ArgumentNullException ("address");
2131 throw new ArgumentNullException ("data");
2133 WebRequest request = null;
2136 cts = new CancellationTokenSource ();
2137 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
2138 var result = await UploadDataTaskAsyncCore (request, encoding.GetBytes (data), cts.Token).ConfigureAwait (false);
2139 var result_str = encoding.GetString (result);
2140 OnUploadStringCompleted (new UploadStringCompletedEventArgs (result_str, null, false, null));
2142 } catch (WebException ex) {
2143 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, ex, false, null));
2145 } catch (OperationCanceledException) {
2146 if (request != null)
2148 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, null, true, null));
2150 } catch (Exception ex) {
2151 OnUploadStringCompleted (new UploadStringCompletedEventArgs (null, ex, true, null));
2152 throw new WebException ("An error occurred performing a WebClient request.", ex);
2156 // UploadValuesTaskAsync
2158 public Task<byte[]> UploadValuesTaskAsync (string address, NameValueCollection data)
2160 if (address == null)
2161 throw new ArgumentNullException ("address");
2163 return UploadValuesTaskAsync (CreateUri (address), data);
2166 public Task<byte[]> UploadValuesTaskAsync (string address, string method, NameValueCollection data)
2168 if (address == null)
2169 throw new ArgumentNullException ("address");
2171 return UploadValuesTaskAsync (CreateUri (address), method, data);
2174 public Task<byte[]> UploadValuesTaskAsync (Uri address, NameValueCollection data)
2176 return UploadValuesTaskAsync (address, (string) null, data);
2179 public async Task<byte[]> UploadValuesTaskAsync (Uri address, string method, NameValueCollection data)
2181 if (address == null)
2182 throw new ArgumentNullException ("address");
2184 throw new ArgumentNullException ("data");
2186 WebRequest request = null;
2189 cts = new CancellationTokenSource ();
2190 request = await SetupRequestAsync (address, method, true).ConfigureAwait (false);
2191 var result = await UploadValuesTaskAsyncCore (request, data, cts.Token).ConfigureAwait (false);
2192 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (result, null, false, null));
2194 } catch (WebException ex) {
2195 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, ex, false, null));
2197 } catch (OperationCanceledException) {
2198 if (request != null)
2200 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, null, true, null));
2202 } catch (Exception ex) {
2203 OnUploadValuesCompleted (new UploadValuesCompletedEventArgs (null, ex, true, null));
2204 throw new WebException ("An error occurred performing a WebClient request.", ex);
2208 async Task<byte[]> UploadValuesTaskAsyncCore (WebRequest request, NameValueCollection data,
2209 CancellationToken token)
2211 token.ThrowIfCancellationRequested ();
2212 string cType = Headers ["Content-Type"];
2213 if (cType != null && String.Compare (cType, urlEncodedCType, true) != 0)
2214 throw new WebException ("Content-Type header cannot be changed from its default " +
2215 "value for this request.");
2217 WebResponse response = null;
2219 Headers ["Content-Type"] = urlEncodedCType;
2221 MemoryStream tmpStream = new MemoryStream ();
2222 foreach (string key in data) {
2223 byte [] bytes = Encoding.UTF8.GetBytes (key);
2224 UrlEncodeAndWrite (tmpStream, bytes);
2225 tmpStream.WriteByte ((byte) '=');
2226 bytes = Encoding.UTF8.GetBytes (data [key]);
2227 UrlEncodeAndWrite (tmpStream, bytes);
2228 tmpStream.WriteByte ((byte) '&');
2231 token.ThrowIfCancellationRequested ();
2233 int length = (int) tmpStream.Length;
2235 tmpStream.SetLength (--length); // remove trailing '&'
2237 byte [] buf = tmpStream.GetBuffer ();
2238 request.ContentLength = length;
2239 using (Stream rqStream = await request.GetRequestStreamAsync ().ConfigureAwait (false)) {
2240 await rqStream.WriteAsync (buf, 0, length, token).ConfigureAwait (false);
2244 response = await GetWebResponseTaskAsync (request, token).ConfigureAwait (false);
2245 return await ReadAllTaskAsync (request, response, token).ConfigureAwait (false);
2247 if (response != null)