public DriveResponse <DriveEmptyDataInfo> Execute(DriveClient driveClient) { var log = Log; log.Debug("Execute: Downloading a file."); var driveFile = DriveFile; if (driveFile == null) { var request = new DriveFileGetRequest(FileId); var response = driveClient.Execute(request); DriveFile = driveFile = response.Data; } var uriItems = driveFile.DownloadUrl.Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries); IRestResponse restResponse; long rangeBegin = 0; uint chunkSize = ChunkSize ?? DefaultChunkSize; var responseWriter = ResponseWriter; long fileSize = driveFile.FileSize; RaiseDownloadProgress(0, fileSize); IRestClient restClient = driveClient.CreateRestClient(uriItems[0]); int timeout = WriteChunkTimeout ?? DefaultWriteChunkTimeout; do { IRestRequest restRequest = CreateRestRequest(uriItems.Length > 1 ? uriItems[1] : string.Empty); restRequest.Timeout = timeout; long rangeEnd = Math.Min(rangeBegin + chunkSize, fileSize - 1); string rangeStr = string.Format("bytes={0}-{1}", rangeBegin, rangeEnd); log.Trace("Execute: Downloading a chunk of file. FilePos: \"{0}\"; BufferLen: \"{1}\"; FileLen: \"{2}\"", rangeBegin, rangeEnd - rangeBegin, fileSize); restRequest.AddParameter("Range", rangeStr, ParameterType.HttpHeader); restRequest.ResponseWriter = stream => stream.CopyTo(responseWriter); restResponse = RequestHandler.Request(restClient, restRequest, HttpStatusCode.OK, HttpStatusCode.PartialContent); if (restResponse.StatusCode == HttpStatusCode.PartialContent) { uriItems = restResponse.ResponseUri.ToString().Split(new[] { '?' }, StringSplitOptions.RemoveEmptyEntries); string rangeResultStr = GetUploadedRange(restResponse, ref rangeBegin, ref rangeEnd, ref fileSize); log.Trace("Execute: Chunk downloaded. Content-Range: \"{0}\"", rangeResultStr); RaiseDownloadProgress(rangeEnd, fileSize); rangeBegin = rangeEnd + 1; if (rangeBegin >= fileSize) { break; } } restClient.BaseUrl = uriItems[0]; } while (restResponse.StatusCode == HttpStatusCode.PartialContent); var result = new DriveResponse <DriveEmptyDataInfo>(restResponse); return(result); }
public DriveResponse <DriveFileInfo> Execute(DriveClient driveClient) { Log.Debug("Execute: Uploading a file."); if (driveClient == null) { throw new ArgumentNullException("driveClient"); } uint chunkSize = ChunkSize ?? DefaultChunkSize; int writeChunkTimeout = WriteChunkTimeout ?? DefaultWriteChunkTimeout; DriveResponse <DriveFileInfo> result = Upload(this, driveClient, chunkSize, writeChunkTimeout); return(result); }
public DriveResponse <T> Execute(DriveClient driveClient) { Log.Debug("Execute"); if (driveClient == null) { throw new ArgumentNullException("driveClient"); } IRestClient restClient = DoGetRestClient(driveClient); IRestRequest restRequest = DoGetRestRequest(driveClient, restClient); restRequest.Timeout = Timeout ?? DefaultTimeout; HttpStatusCode[] expectedStatusCodes = ExpectedStatusCodes; IRestResponse <T> restResponse = RequestHandler.Request <T>(restClient, restRequest, expectedStatusCodes); var result = new DriveResponse <T>(restResponse); return(result); }
/// <summary> /// Uploads a file with a specified chunk size. /// </summary> /// <param name="request">The uploading file request.</param> /// <param name="driveClient">The Google Drive client.</param> /// <param name="chunkSize">The file chunk size.</param> /// <param name="writeChunkTimeout">The timeout in milliseconds to write a file chunk.</param> /// <returns>A response with information about remote file.</returns> private static DriveResponse <DriveFileInfo> Upload(DriveFileUploadRequest request, DriveClient driveClient, uint chunkSize, int writeChunkTimeout) { const string locationHeaderName = "Location"; var log = Log; log.Debug("Upload: Chunk size: \"{0}\"", chunkSize); var stream = request.LocalStream; var initRestRequest = CreateInitRestRequest(request); var driveRestClient = driveClient.DriveRestClient; var initRestResponse = RequestHandler.Request(driveRestClient, initRestRequest, HttpStatusCode.OK); var locationHeader = initRestResponse.Headers.FirstOrDefault(x => x.Name == locationHeaderName); IRestResponse lastrestResponse = initRestResponse; if (locationHeader != null) { string uploadContentType = request.UploadContentType; var location = locationHeader.Value as string; Debug.Assert(location != null, "location != null"); var uploadClient = new RestClient(location) { Authenticator = driveClient.Authenticator.RestAuthenticator }; var buffer = new byte[chunkSize]; long filePos = 0, fileLen = stream.Length; int bufferLen; request.RaiseUploadProgress(filePos, fileLen); while ((bufferLen = stream.Read(buffer, 0, buffer.Length)) > 0) { const string rangeHeaderName = "Range"; log.Trace("Upload: Uploading a chunk of file. FilePos: \"{0}\"; BufferLen: \"{1}\"; FileLen: \"{2}\"", filePos, bufferLen, fileLen); var data = bufferLen < buffer.Length ? CreateArray(buffer, 0, bufferLen) : buffer; IRestRequest uploadRestRequest = CreateUploadRestRequest(uploadContentType, chunkSize, filePos, bufferLen, fileLen, data); uploadRestRequest.Timeout = writeChunkTimeout; lastrestResponse = RequestHandler.Request(uploadClient, uploadRestRequest, ResumeIncomplete, HttpStatusCode.Created, HttpStatusCode.OK); if (lastrestResponse.StatusCode == HttpStatusCode.Created || lastrestResponse.StatusCode == HttpStatusCode.OK) { request.RaiseUploadProgress(filePos + bufferLen, fileLen); break; } var rangeResultHeader = lastrestResponse.Headers.FirstOrDefault(x => x.Name == rangeHeaderName); if (rangeResultHeader != null) { var rangeResultStr = rangeResultHeader.Value as string; if (rangeResultStr == null) { throw new InteractionException(MessageDefs.ClientName, MessageDefs.InvalidRangeHeaderOfUploadResponse, lastrestResponse.StatusCode, lastrestResponse.StatusDescription, string.Format(LocalStrings.RangeHeaderInvalidErrorMessage1, rangeResultHeader.Value)); } string[] rangeResultItems = rangeResultStr.Replace(" ", string.Empty).Split('-'); if (rangeResultItems.Length > 1) { long endRange; if (long.TryParse(rangeResultItems[1], out endRange)) { filePos = endRange == 0 ? 0 : endRange + 1; if (filePos != stream.Position) { stream.Seek(filePos, SeekOrigin.Begin); } request.RaiseUploadProgress(filePos, fileLen); } else { throw new InteractionException(MessageDefs.ClientName, MessageDefs.InvalidRangeHeaderOfUploadResponse, lastrestResponse.StatusCode, lastrestResponse.StatusDescription, string.Format(LocalStrings.RangeHeaderInvalidEndErrorMessage1, rangeResultStr)); } } else { throw new InteractionException(MessageDefs.ClientName, MessageDefs.InvalidRangeHeaderOfUploadResponse, lastrestResponse.StatusCode, lastrestResponse.StatusDescription, string.Format(LocalStrings.RangeHeaderInvalidEndErrorMessage1, rangeResultStr)); } } else { throw new InteractionException(MessageDefs.ClientName, MessageDefs.NoRangeHeaderOfUploadResponse, lastrestResponse.StatusCode, lastrestResponse.StatusDescription, LocalStrings.RangeHeaderNotExistErrorMessage); } } } else { throw new InteractionException(MessageDefs.ClientName, MessageDefs.NoLocationHeaderOfUploadResponse, lastrestResponse.StatusCode, lastrestResponse.StatusDescription, LocalStrings.LocationHeaderNotExistsMessage); } var result = new DriveResponse <DriveFileInfo>(lastrestResponse); return(result); }