/// <summary> /// Creates initialization REST request. /// </summary> /// <param name="request">The instance of uploading file request.</param> /// <returns>A REST request to initialize uploading a file with chunks.</returns> private static IRestRequest CreateInitRestRequest(DriveFileUploadRequest request) { var result = RestRequestFactory.CreateRestRequest(ServiceDefs.Drive.DriveUploadFilesResource, Method.POST, request, true); result.AddParameter("X-Upload-Content-Type", request.UploadContentType, ParameterType.HttpHeader); result.AddParameter("X-Upload-Content-Length", request.LocalStream.Length, ParameterType.HttpHeader); 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); }