public async Task OnFailedAsync(UploadExceptionEvent @event,
                                        CancellationToken ct)
        {
            var exception = await ParseExceptionAsync(@event.Response, @event.Exception, ct);

            await inner.OnFailedAsync(new AssetUploadExceptionEvent(@event.FileId, exception), ct);
        }
Example #2
0
        /// <summary>
        /// Uploads the file.
        /// </summary>
        /// <returns>The upload id.</returns>
        /// <param name="filePath">File path.</param>
        /// <param name="uploadName">Upload name.</param>
        /// <param name="maxPartRetry">Max part retry.</param>
        public async Task <string> UploadFile(string filePath, string uploadName, int maxPartRetry = 3, long maxPartSize = 6000000L)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException(nameof(filePath));
            }
            if (string.IsNullOrWhiteSpace(uploadName))
            {
                throw new ArgumentNullException(nameof(uploadName));
            }
            if (maxPartRetry < 1)
            {
                throw new ArgumentException("Max Part Retry needs to be greater than or equal to 1", nameof(maxPartRetry));
            }
            if (maxPartSize < 1)
            {
                throw new ArgumentException("Max Part Size needs to be greater than 0", nameof(maxPartSize));
            }

            var fileInfo    = new FileInfo(filePath);
            var contentType = MimeGuesser.GuessFileType(filePath).MimeType;

            Amazon.S3.Model.InitiateMultipartUploadResponse multiPartStart;

            using (var client = CreateNewClient())
            {
                multiPartStart = await client.InitiateMultipartUploadAsync(new Amazon.S3.Model.InitiateMultipartUploadRequest()
                {
                    BucketName  = _spaceName,
                    ContentType = contentType,
                    Key         = uploadName
                });

                var estimatedParts = (int)(fileInfo.Length / maxPartSize);
                if (estimatedParts == 0)
                {
                    estimatedParts = 1;
                }

                UploadStatusEvent?.Invoke(this, new UploadStatus(0, estimatedParts, 0, fileInfo.Length));

                try
                {
                    var i = 0L;
                    var n = 1;
                    Dictionary <string, int> parts = new Dictionary <string, int>();
                    while (i < fileInfo.Length)
                    {
                        long partSize = maxPartSize;
                        var  lastPart = (i + partSize) >= fileInfo.Length;
                        if (lastPart)
                        {
                            partSize = fileInfo.Length - i;
                        }
                        bool complete = false;
                        int  retry    = 0;
                        Amazon.S3.Model.UploadPartResponse partResp = null;
                        do
                        {
                            retry++;
                            try
                            {
                                partResp = await client.UploadPartAsync(new Amazon.S3.Model.UploadPartRequest()
                                {
                                    BucketName   = _spaceName,
                                    FilePath     = filePath,
                                    FilePosition = i,
                                    IsLastPart   = lastPart,
                                    PartSize     = partSize,
                                    PartNumber   = n,
                                    UploadId     = multiPartStart.UploadId,
                                    Key          = uploadName
                                });

                                complete = true;
                            }
                            catch (Exception ex)
                            {
                                UploadExceptionEvent?.Invoke(this, new UploadException($"Failed to upload part {n} on try #{retry}", ex));
                            }
                        } while (!complete && retry <= maxPartRetry);

                        if (!complete || partResp == null)
                        {
                            throw new Exception($"Unable to upload part {n}");
                        }

                        parts.Add(partResp.ETag, n);
                        i += partSize;
                        UploadStatusEvent?.Invoke(this, new UploadStatus(n, estimatedParts, i, fileInfo.Length));
                        n++;
                    }

                    // upload complete
                    var completePart = await client.CompleteMultipartUploadAsync(new Amazon.S3.Model.CompleteMultipartUploadRequest()
                    {
                        UploadId   = multiPartStart.UploadId,
                        BucketName = _spaceName,
                        Key        = uploadName,
                        PartETags  = parts.Select(p => new Amazon.S3.Model.PartETag(p.Value, p.Key)).ToList()
                    });
                }
                catch (Exception ex)
                {
                    var abortPart = await client.AbortMultipartUploadAsync(_spaceName, uploadName, multiPartStart.UploadId);

                    UploadExceptionEvent?.Invoke(this, new UploadException("Something went wrong upload file and it was aborted", ex));
                }
            }

            return(multiPartStart?.UploadId);
        }