public UploadFileChunksTask(UploadInfo file, IUploadProgressReporter progressReporter, CancellationToken token, IApiHelper apiHelper) : base(apiHelper) { _file = file; _filePath = file.FilePath; _fileSize = file.FileSize; _progressReporter = progressReporter; _token = token; _deckCloudFileResponse = file.DeckCloudFileResponse; }
public UploadFileChunksTask(string filePath, long fileSize, DeckCloudFileResponse response, CancellationToken token, IApiHelper apiHelper) : base(apiHelper) { _file = null; _filePath = filePath; _fileSize = fileSize; _progressReporter = null; _token = token; _deckCloudFileResponse = response; }
public void Restart() { Stage = AttachmentStage.Pending; CurrentChunk = 0; UploadedBytes = 0; DeckCloudFileResponse = null; DeckVersionResponse = null; Status = AttachmentStatus.Pending; DownloadLink = null; }
public void FinishChunking(DeckCloudFileResponse initiateChunkingResponse) { if (string.IsNullOrEmpty(_deviceToken)) { throw new Exception("Device token is blank."); } // Finishing file chunk uploading. Logger.LogDebug("Finishing file chunk uploading."); string uri = string.Format("{0}/cloud_files/{1}.xml", m_hostServer, initiateChunkingResponse.FileDataId); var parameters = new List<NamedData> { new NamedData("complete_multipart", "true"), new NamedData("multipart_upload_id", initiateChunkingResponse.UploadId) }; // Specify a schema to ensure the response is as expected. string xmlSchema = Resources.DeckCloudFileXmlSchema; DataSet dset = MultipartFormDataPut(uri, parameters, xmlSchema); var finishChunkingResponse = new DeckCloudFileResponse(dset, DeckCloudFileResponse.RequestType.FinishChunking); if (finishChunkingResponse.FileDataId != initiateChunkingResponse.FileDataId) { throw new InvalidResponseException("The finish chunking response \"file data ID\" does not match the initiate chunking response."); } }
public int UploadChunk(FileStream file, DeckCloudFileResponse deckResponse, long? position = null) { try { // Upload a file chunk. Logger.LogDebug("Upload a file chunk."); // Reposition file stream to chunk position if provided if (position.HasValue) { file.Position = position.Value; } // Read from the file into a buffer. It's either the full chunk size or the last chunk's remaining size. long remainingBytesLength = file.Length - file.Position; int chunkSize = (remainingBytesLength < FILE_UPLOAD_CHUNK_SIZE) ? (int) remainingBytesLength : FILE_UPLOAD_CHUNK_SIZE; Logger.LogInfo(string.Format("Read {0} bytes from the file into a buffer.", chunkSize)); file.Read(m_buffer, 0, chunkSize); // Creating HTTP web request to Amazon Web Services (AWS). Logger.LogDebug("Creating HTTP web request."); var request = CreateWebRequest(deckResponse.DeckCloudUploadInfo.Action); request.Method = WebRequestMethods.Http.Put; request.ContentType = deckResponse.DeckCloudUploadInfo.ContentType; request.AllowAutoRedirect = false; request.AllowWriteStreamBuffering = true; request.ContentLength = chunkSize; // Add headers specific to AWS. request.Headers.Add("authorization", deckResponse.DeckCloudUploadInfo.Authorization); request.Headers.Add("x-amz-date", deckResponse.DeckCloudUploadInfo.XAmzDate); // Get request stream. Logger.LogDebug("Getting request stream."); using (Stream requestStream = request.GetRequestStream()) { // Writing to request stream. Logger.LogDebug("Writing to request stream."); requestStream.Write(m_buffer, 0, chunkSize); } // The schema here is null because the AWS web service call just responds // with an OK when successful and there is no XML data returned. CompleteMultipartFormData(false, null, request); return chunkSize; } finally { Array.Clear(m_buffer, 0, m_buffer.Length); } }
public DeckCloudFileResponse RequestChunkParameters(DeckCloudFileResponse initiateChunkingResponse, long partNumber) { // Request file chunk parameters. Logger.LogDebug("Request file chunk parameters."); string uri = string.Format("{0}/cloud_files/{1}.xml", m_hostServer, initiateChunkingResponse.FileDataId); var parameters = new List<NamedData> { new NamedData("multipart_upload_id", initiateChunkingResponse.UploadId), new NamedData("part_number", partNumber) }; // Specify a schema to ensure the response is as expected. string xmlSchema = Resources.DeckCloudFileXmlSchema; DataSet dset = MultipartFormDataGet(uri, parameters, true, false, xmlSchema); return new DeckCloudFileResponse(dset, DeckCloudFileResponse.RequestType.RequestChunk); }
public void UploadFileChunks(Action<long, double> callbackIncrementProgress, string filePath, DeckCloudFileResponse initiateChunkingResponse) { if (string.IsNullOrEmpty(_deviceToken)) { throw new Exception("Device token is blank."); } Logger.LogDebug(string.Format("Opening file \"{0}\" to be uploaded in chunks.", filePath)); // Open the file as a stream. using (FileStream file = File.OpenRead(filePath)) { // Determine how many chunks will need to be sent. long totalChunks = file.Length / FILE_UPLOAD_CHUNK_SIZE; if (file.Length % FILE_UPLOAD_CHUNK_SIZE != 0) { // There was a remainder to the division, so add one to account for it. totalChunks++; } Logger.LogDebug(string.Format("Uploading file in {0} chunks (max chunk length: {1}MB).", totalChunks, FILE_UPLOAD_CHUNK_SIZE / 1024 / 1024)); for (int partNumber = 1; partNumber <= totalChunks; partNumber++) { DeckCloudFileResponse requestChunkResponse = RequestChunkParameters(initiateChunkingResponse, partNumber); DateTime start = DateTime.Now; int bytesUploaded = UploadChunk(file, requestChunkResponse); TimeSpan duration = DateTime.Now - start; var byteRate = (double) bytesUploaded / duration.TotalSeconds; if (callbackIncrementProgress != null) { Logger.LogDebug("Calling delegate to increment progress."); // The bytesUploaded will always be 5MB or less, thus // an int will suffice. The int is cast to a long here. callbackIncrementProgress(bytesUploaded, byteRate); } } } }