public async Task <HttpWebResponse> GetDownloadResponseAsync([NotNull] string driveId, [NotNull] string itemId, long?from, CancellationToken cancellationToken) { var downloadUrl = GetDownloadUrl(driveId, itemId); var request = await _restClientFactory.CreateWebRequest(new Uri(downloadUrl)); if (from != null) { if (_addRangeMethod != null) { _addRangeMethod.Invoke(request, new object[] { from.Value }); } else { var range = new HttpRange("bytes", new HttpRangeItem(from, null)); request.Headers[HttpRequestHeader.Range] = range.ToString(); } } var response = (HttpWebResponse)await Task.Factory.FromAsync <WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); return(response); }
public async Task <Item> UploadFileAsync([NotNull] string driveId, [NotNull] string parentId, [NotNull] string name, [NotNull] Stream input, CancellationToken cancellationToken) { // Create upload session var request = CreateRequest($"drives/{driveId}/items/{parentId}:/{name}:/upload.createSession"); request.AddBody( new { Item = new Item { Name = name, ConflictBehavior = ConflictBehavior.Replace, }, }); var deserializer = new JsonDeserializer(); var response = await _restClient.Execute <UploadSession>(request, cancellationToken); var uploadSession = response.Data; var inputLength = input.Length; var sessionUri = uploadSession.UploadUrl; // Upload the data using (var uploadClient = CreateClient()) { uploadClient.IgnoreResponseStatusCode = true; int blockSize = 262144; // Info from Google PUT error message var buffer = new byte[blockSize]; byte[] temp = null; // As long as we have an upload session, upload the data... while (uploadSession != null) { IRestResponse fragmentUploadResponse = null; // Upload all data requested by the given ranges var ranges = uploadSession.ToHttpRange(); foreach (var range in ranges.Normalize(input.Length)) { // Split the data to upload into blocks (to keep memory usage small) int size; var length = range.Length; for (long i = 0; i != length; i += size) { size = (int)Math.Min(range.Length, blockSize); var readSize = input.Read(buffer, 0, size); if (readSize == 0) { throw new InvalidOperationException($"Failed to read {size} bytes from position {i}"); } size = readSize; var requestRange = new HttpRange("bytes", new HttpRangeItem(range.From + i, range.From + i + size - 1)); if (temp == null || temp.Length != size) { temp = new byte[size]; } Array.Copy(buffer, temp, size); var requestUploadChunk = CreateRequest(sessionUri, Method.PUT); requestUploadChunk.AddHeader("Content-Range", requestRange.ToString(requestRange.RangeItems.Single(), inputLength)); requestUploadChunk.AddParameter(string.Empty, temp, ParameterType.RequestBody, "application/octet-stream"); fragmentUploadResponse = await uploadClient.Execute(requestUploadChunk, cancellationToken); if (!fragmentUploadResponse.IsSuccess) { throw new WebException(fragmentUploadResponse.StatusDescription, WebExceptionStatus.UnknownError); } } } if (fragmentUploadResponse != null) { // Deserialize the data into a JObject var data = deserializer.Deserialize <JObject>(fragmentUploadResponse); if (data.Property("id") == null) { // Convert to a new UploadSession when we don't have the "id" property uploadSession = data.ToObject <UploadSession>(); } else { // Otherwise return the data (which means: we just uploaded the last chunk) var item = data.ToObject <Item>(); return(item); } } else { // should never happen... uploadSession = null; } } } // We didn't receive an "Item" object in the last upload chunk: Just query it // from the server ourselves. var result = await GetChildItemAsync(driveId, parentId, name, cancellationToken); if (result == null) { throw new InvalidOperationException(); } return(result); }
public async Task<Item> UploadFileAsync([NotNull] string driveId, [NotNull] string parentId, [NotNull] string name, [NotNull] Stream input, CancellationToken cancellationToken) { // Create upload session var request = CreateRequest($"drives/{driveId}/items/{parentId}:/{name}:/upload.createSession"); request.AddBody( new { Item = new Item { Name = name, ConflictBehavior = ConflictBehavior.Replace, }, }); var deserializer = new JsonDeserializer(); var response = await _restClient.Execute<UploadSession>(request, cancellationToken); var uploadSession = response.Data; var inputLength = input.Length; var sessionUri = uploadSession.UploadUrl; // Upload the data using (var uploadClient = CreateClient()) { uploadClient.IgnoreResponseStatusCode = true; int blockSize = 262144; // Info from Google PUT error message var buffer = new byte[blockSize]; byte[] temp = null; // As long as we have an upload session, upload the data... while (uploadSession != null) { IRestResponse fragmentUploadResponse = null; // Upload all data requested by the given ranges var ranges = uploadSession.ToHttpRange(); foreach (var range in ranges.Normalize(input.Length)) { // Split the data to upload into blocks (to keep memory usage small) int size; var length = range.Length; for (long i = 0; i != length; i += size) { size = (int)Math.Min(range.Length, blockSize); var readSize = input.Read(buffer, 0, size); if (readSize == 0) throw new InvalidOperationException($"Failed to read {size} bytes from position {i}"); size = readSize; var requestRange = new HttpRange("bytes", new HttpRangeItem(range.From + i, range.From + i + size - 1)); if (temp == null || temp.Length != size) temp = new byte[size]; Array.Copy(buffer, temp, size); var requestUploadChunk = CreateRequest(sessionUri, Method.PUT); requestUploadChunk.AddHeader("Content-Range", requestRange.ToString(requestRange.RangeItems.Single(), inputLength)); requestUploadChunk.AddParameter(string.Empty, temp, ParameterType.RequestBody, "application/octet-stream"); fragmentUploadResponse = await uploadClient.Execute(requestUploadChunk, cancellationToken); if (!fragmentUploadResponse.IsSuccess) throw new WebException(fragmentUploadResponse.StatusDescription, WebExceptionStatus.UnknownError); } } if (fragmentUploadResponse != null) { // Deserialize the data into a JObject var data = deserializer.Deserialize<JObject>(fragmentUploadResponse); if (data.Property("id") == null) { // Convert to a new UploadSession when we don't have the "id" property uploadSession = data.ToObject<UploadSession>(); } else { // Otherwise return the data (which means: we just uploaded the last chunk) var item = data.ToObject<Item>(); return item; } } else { // should never happen... uploadSession = null; } } } // We didn't receive an "Item" object in the last upload chunk: Just query it // from the server ourselves. var result = await GetChildItemAsync(driveId, parentId, name, cancellationToken); if (result == null) throw new InvalidOperationException(); return result; }
public async Task<HttpWebResponse> GetDownloadResponseAsync([NotNull] string driveId, [NotNull] string itemId, long? from, CancellationToken cancellationToken) { var downloadUrl = GetDownloadUrl(driveId, itemId); var request = await _restClientFactory.CreateWebRequest(new Uri(downloadUrl)); if (from != null) { if (_addRangeMethod != null) { _addRangeMethod.Invoke(request, new object[] { from.Value }); } else { var range = new HttpRange("bytes", new HttpRangeItem(from, null)); request.Headers[HttpRequestHeader.Range] = range.ToString(); } } var response = (HttpWebResponse)await Task.Factory.FromAsync<WebResponse>(request.BeginGetResponse, request.EndGetResponse, null); return response; }