Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code | Sign in
(291)

Side by Side Diff: Src/GoogleApis/Apis/[Media]/Download/MediaDownloader.cs

Issue 13480044: Issue 361: MediaDownloader can't download drive export list (which includes query parameters) (Closed) Base URL: https://google-api-dotnet-client.googlecode.com/hg/
Patch Set: minor Created 10 years, 9 months ago
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments. Please Sign in to add in-line comments.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 Copyright 2013 Google Inc 2 Copyright 2013 Google Inc
3 3
4 Licensed under the Apache License, Version 2.0 (the "License"); 4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License. 5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at 6 You may obtain a copy of the License at
7 7
8 http://www.apache.org/licenses/LICENSE-2.0 8 http://www.apache.org/licenses/LICENSE-2.0
9 9
10 Unless required by applicable law or agreed to in writing, software 10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS, 11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and 13 See the License for the specific language governing permissions and
14 limitations under the License. 14 limitations under the License.
15 */ 15 */
16 16
17 using System; 17 using System;
18 using System.Linq;
18 using System.IO; 19 using System.IO;
19 using System.Net.Http.Headers; 20 using System.Net.Http.Headers;
20 using System.Threading; 21 using System.Threading;
21 using System.Threading.Tasks; 22 using System.Threading.Tasks;
22 23
23 using Google.Apis.Requests; 24 using Google.Apis.Requests;
24 using Google.Apis.Services; 25 using Google.Apis.Services;
25 using Google.Apis.Util; 26 using Google.Apis.Util;
26 27
27 namespace Google.Apis.Download 28 namespace Google.Apis.Download
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
182 CancellationToken cancellationToken) 183 CancellationToken cancellationToken)
183 { 184 {
184 // validate the parameters 185 // validate the parameters
185 url.ThrowIfNull("url"); 186 url.ThrowIfNull("url");
186 stream.ThrowIfNull("stream"); 187 stream.ThrowIfNull("stream");
187 if (!stream.CanWrite) 188 if (!stream.CanWrite)
188 { 189 {
189 throw new ArgumentException("stream doesn't support write operat ions"); 190 throw new ArgumentException("stream doesn't support write operat ions");
190 } 191 }
191 192
192 var builder = new RequestBuilder() { BaseUri = new Uri(url) }; 193 RequestBuilder builder = null;
194
195 var uri = new Uri(url);
196 if (string.IsNullOrEmpty(uri.Query))
197 {
198 builder = new RequestBuilder() { BaseUri = new Uri(url) };
199 }
200 else
201 {
202 builder = new RequestBuilder() { BaseUri = new Uri(url.Substring (0, url.IndexOf("?"))) };
203 // remove '?' at the beginning
204 var query = uri.Query.Substring(1);
205 var pairs = from parameter in query.Split('&')
206 select parameter.Split('=');
207 // add each query parameter. each pair contains the key [0] and then its value [1]
208 foreach (var p in pairs)
209 {
210 builder.AddParameter(RequestParameterType.Query, p[0], p[1]) ;
211 }
212 }
193 builder.AddParameter(RequestParameterType.Query, "alt", "media"); 213 builder.AddParameter(RequestParameterType.Query, "alt", "media");
194 214
195 long currentRequestFirstBytePos = 0; 215 long currentRequestFirstBytePos = 0;
196 216
197 try 217 try
198 { 218 {
199 // this "infinite" loop stops when the "to" byte position in the "Content-Range" header is the last 219 // this "infinite" loop stops when the "to" byte position in the "Content-Range" header is the last
200 // byte of the media ("length"-1 in the "Content-Range" header). 220 // byte of the media ("length"-1 in the "Content-Range" header).
201 // e.g. "Content-Range: 200-299/300" - "to"(299) = "length"(300) - 1. 221 // e.g. "Content-Range: 200-299/300" - "to"(299) = "length"(300) - 1.
202 while (true) 222 while (true)
203 { 223 {
204 cancellationToken.ThrowIfCancellationRequested(); 224 cancellationToken.ThrowIfCancellationRequested();
205 225
206 var currentRequestLastBytePos = currentRequestFirstBytePos ChunkSize - 1; 226 var currentRequestLastBytePos = currentRequestFirstBytePos ChunkSize - 1;
207 227
208 // create the request and set the Range header 228 // create the request and set the Range header
209 var request = builder.CreateRequest(); 229 var request = builder.CreateRequest();
210 request.Headers.Range = new RangeHeaderValue(currentRequestF irstBytePos, 230 request.Headers.Range = new RangeHeaderValue(currentRequestF irstBytePos,
211 currentRequestLastBytePos); 231 currentRequestLastBytePos);
212 232
213 using (var response = await service.HttpClient.SendAsync(req uest, cancellationToken). 233 using (var response = await service.HttpClient.SendAsync(req uest, cancellationToken).
214 ConfigureAwait(false)) 234 ConfigureAwait(false))
215 { 235 {
216 // read the content and copy to the parameter's stream 236 // read the content and copy to the parameter's stream
217 var responseStream = await response.Content.ReadAsStream Async().ConfigureAwait(false); 237 var responseStream = await response.Content.ReadAsStream Async().ConfigureAwait(false);
218 responseStream.CopyTo(stream); 238 responseStream.CopyTo(stream);
219 239
220 // read the headers and check if all the media content w as already downloaded 240 // read the headers and check if all the media content w as already downloaded
221 var contentRange = response.Content.Headers.ContentRange ; 241 var contentRange = response.Content.Headers.ContentRange ;
222 currentRequestFirstBytePos = contentRange.To.Value 1; 242 long mediaContentLength;
223 long mediaContentLength = contentRange.Length.Value; 243
244 if (contentRange == null)
245 {
246 // content range is null when the server doesn't adh ere the media download protocol, in·
247 // that case we got all the media in one chunk
248 currentRequestFirstBytePos = mediaContentLength =
249 response.Content.Headers.ContentLength.Value;
250 }
251 else
252 {
253 currentRequestFirstBytePos = contentRange.To.Value 1;
254 mediaContentLength = contentRange.Length.Value;
255 }
224 256
225 if (currentRequestFirstBytePos == mediaContentLength) 257 if (currentRequestFirstBytePos == mediaContentLength)
226 { 258 {
227 var progress = new DownloadProgress(DownloadStatus.C ompleted, mediaContentLength); 259 var progress = new DownloadProgress(DownloadStatus.C ompleted, mediaContentLength);
228 UpdateProgress(progress); 260 UpdateProgress(progress);
229 return progress; 261 return progress;
230 } 262 }
231 } 263 }
232 264
233 UpdateProgress(new DownloadProgress(DownloadStatus.Downloadi ng, currentRequestFirstBytePos)); 265 UpdateProgress(new DownloadProgress(DownloadStatus.Downloadi ng, currentRequestFirstBytePos));
234 } 266 }
235 } 267 }
236 catch (Exception ex) 268 catch (Exception ex)
237 { 269 {
238 var progress = new DownloadProgress(ex, currentRequestFirstByteP os); 270 var progress = new DownloadProgress(ex, currentRequestFirstByteP os);
239 UpdateProgress(progress); 271 UpdateProgress(progress);
240 return progress; 272 return progress;
241 } 273 }
242 } 274 }
243 } 275 }
244 } 276 }
OLDNEW

Powered by Google App Engine
RSS Feeds Recent Issues | This issue
This is Rietveld f62528b