Esempio n. 1
0
        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);
        }