Exemplo n.º 1
0
        /// <summary>
        /// Split a file into chunks
        /// </summary>
        /// <param name="initiateFileUploadInfo">The information used to initiate a file upload</param>
        /// <param name="initiateFileUploadResponse">The response to the request to initiate a file upload</param>
        /// <returns>Information to upload each chunk</returns>
        private IList <UploadChunkInfo> ChunkFile(InitiateFileUploadInfo initiateFileUploadInfo,
                                                  InitiateFileUploadResponse initiateFileUploadResponse)
        {
            var chunks = new List <UploadChunkInfo>();

            using (var inputFileStream = File.OpenRead(initiateFileUploadInfo.Path))
            {
                for (int chunkIndex = 0; chunkIndex < initiateFileUploadInfo.NumberOfChunks; chunkIndex++)
                {
                    string chunkPath;
                    long   chunkSize;
                    if (initiateFileUploadInfo.NumberOfChunks > 1)
                    {
                        chunkPath = Path.GetTempFileName();

                        // When chunking, chunk size can NOT be smaller than UPLOAD_CHUNK_SIZE_IN_BYTES, i.e., the last chunk will
                        // be between UPLOAD_CHUNK_SIZE_IN_BYTES and 2 * UPLOAD_CHUNK_SIZE_IN_BYTES
                        chunkSize = chunkIndex < initiateFileUploadInfo.NumberOfChunks - 1 ? UPLOAD_CHUNK_SIZE_IN_BYTES :
                                    initiateFileUploadInfo.FileSize - chunkIndex * UPLOAD_CHUNK_SIZE_IN_BYTES;

                        using (var outputFileStream = File.OpenWrite(chunkPath))
                        {
                            var totalNumberOfBytesCopied = CopyStream(inputFileStream, outputFileStream, chunkSize);
                            if (totalNumberOfBytesCopied != chunkSize)
                            {
                                var message = $"Error creating chunk {chunkIndex + 1} of {initiateFileUploadInfo.NumberOfChunks} for file {initiateFileUploadInfo.Path}.  Only {totalNumberOfBytesCopied} of {chunkSize} bytes were copied.";
                                _logger.LogError(message);
                                throw new ProKnowException(message);
                            }
                        }
                    }
                    else
                    {
                        chunkPath = initiateFileUploadInfo.Path;
                        chunkSize = initiateFileUploadInfo.FileSize;
                    }
                    var chunk = new UploadChunkInfo
                    {
                        InitiateFileUploadInfo     = initiateFileUploadInfo,
                        InitiateFileUploadResponse = initiateFileUploadResponse,
                        ChunkIndex = chunkIndex,
                        ChunkPath  = chunkPath,
                        ChunkSize  = chunkSize
                    };
                    chunks.Add(chunk);
                }
            }

            return(chunks);
        }
Exemplo n.º 2
0
        /// <summary>
        /// Uploads a chunk of a file
        /// </summary>
        /// <param name="uploadChunkInfo">The information to upload a chunk</param>
        private async Task UploadChunkAsync(UploadChunkInfo uploadChunkInfo)
        {
            await _semaphore.WaitAsync();

            try
            {
                var headerKeyValuePairs = new List <KeyValuePair <string, string> >()
                {
                    new KeyValuePair <string, string>("Proknow-Key", uploadChunkInfo.InitiateFileUploadResponse.Key)
                };
                using (var content = new MultipartFormDataContent())
                {
                    content.Add(new StringContent((uploadChunkInfo.ChunkIndex + 1).ToString()), "flowChunkNumber");
                    content.Add(new StringContent(UPLOAD_CHUNK_SIZE_IN_BYTES.ToString()), "flowChunkSize");
                    content.Add(new StringContent(uploadChunkInfo.ChunkSize.ToString()), "flowCurrentChunkSize");
                    content.Add(new StringContent(uploadChunkInfo.InitiateFileUploadInfo.NumberOfChunks.ToString()), "flowTotalChunks");
                    content.Add(new StringContent(uploadChunkInfo.InitiateFileUploadInfo.FileSize.ToString()), "flowTotalSize");
                    content.Add(new StringContent(uploadChunkInfo.InitiateFileUploadResponse.Identifier), "flowIdentifier");
                    content.Add(new StringContent(uploadChunkInfo.InitiateFileUploadInfo.Path), "flowFilename");
                    content.Add(new StringContent((uploadChunkInfo.InitiateFileUploadInfo.NumberOfChunks > 1).ToString().ToLower()), "flowMultipart");
                    using (var fs = File.OpenRead(uploadChunkInfo.ChunkPath))
                    {
                        content.Add(new StreamContent(fs), "file", uploadChunkInfo.InitiateFileUploadInfo.Path);
                        var response = await _proKnow.Requestor.PostAsync("/uploads/chunks", headerKeyValuePairs, content);

                        _logger.LogDebug($"Uploaded file {uploadChunkInfo.InitiateFileUploadInfo.Path} chunk {uploadChunkInfo.ChunkIndex + 1} of {uploadChunkInfo.InitiateFileUploadInfo.NumberOfChunks}.  Response: {response}");
                    }
                }
            }
            catch (Exception ex)
            {
                _logger.LogError($"Error uploading chunk {uploadChunkInfo.ChunkIndex + 1} of {uploadChunkInfo.InitiateFileUploadInfo.NumberOfChunks} for file {uploadChunkInfo.InitiateFileUploadInfo.Path}.  {ex}");
                throw;
            }
            finally
            {
                _semaphore.Release();
            }
        }