Index: Src/GoogleApis/Apis/[Media]/Download/MediaDownloader.cs =================================================================== --- a/Src/GoogleApis/Apis/[Media]/Download/MediaDownloader.cs +++ b/Src/GoogleApis/Apis/[Media]/Download/MediaDownloader.cs @@ -15,6 +15,7 @@ */ using System; +using System.Linq; using System.IO; using System.Net.Http.Headers; using System.Threading; @@ -189,7 +190,26 @@ throw new ArgumentException("stream doesn't support write operations"); } - var builder = new RequestBuilder() { BaseUri = new Uri(url) }; + RequestBuilder builder = null; + + var uri = new Uri(url); + if (string.IsNullOrEmpty(uri.Query)) + { + builder = new RequestBuilder() { BaseUri = new Uri(url) }; + } + else + { + builder = new RequestBuilder() { BaseUri = new Uri(url.Substring(0, url.IndexOf("?"))) }; + // remove '?' at the beginning + var query = uri.Query.Substring(1); + var pairs = from parameter in query.Split('&') + select parameter.Split('='); + // add each query parameter. each pair contains the key [0] and then its value [1] + foreach (var p in pairs) + { + builder.AddParameter(RequestParameterType.Query, p[0], p[1]); + } + } builder.AddParameter(RequestParameterType.Query, "alt", "media"); long currentRequestFirstBytePos = 0; @@ -219,8 +239,20 @@ // read the headers and check if all the media content was already downloaded var contentRange = response.Content.Headers.ContentRange; - currentRequestFirstBytePos = contentRange.To.Value + 1; - long mediaContentLength = contentRange.Length.Value; + long mediaContentLength; + + if (contentRange == null) + { + // content range is null when the server doesn't adhere the media download protocol, in + // that case we got all the media in one chunk + currentRequestFirstBytePos = mediaContentLength = + response.Content.Headers.ContentLength.Value; + } + else + { + currentRequestFirstBytePos = contentRange.To.Value + 1; + mediaContentLength = contentRange.Length.Value; + } if (currentRequestFirstBytePos == mediaContentLength) {