Ejemplo n.º 1
0
        public async Task UploadFilePart(MultipartUploadSession uploadSession, Stream inputStream, int templateCode)
        {
            if (SessionDescriptor.IsSessionExpired(uploadSession.SessionExpiresAt))
            {
                throw new SessionExpiredException(uploadSession.SessionId, uploadSession.SessionExpiresAt);
            }

            if (uploadSession.NextPartNumber == 1)
            {
                var sessionDescriptor = uploadSession.SessionDescriptor;
                var elementDescriptor = uploadSession.ElementDescriptor;
                EnsureFileHeaderIsValid(
                    templateCode,
                    uploadSession.ElementDescriptor.Type,
                    elementDescriptor.Constraints.For(sessionDescriptor.Language),
                    inputStream,
                    uploadSession.UploadedFileMetadata);
            }

            var key = uploadSession.SessionId.AsS3ObjectKey(uploadSession.FileKey);

            inputStream.Position = 0;

            var response = await _cephS3Client.UploadPartAsync(
                new UploadPartRequest
            {
                BucketName  = _filesBucketName,
                Key         = key,
                UploadId    = uploadSession.UploadId,
                InputStream = inputStream,
                PartNumber  = uploadSession.NextPartNumber
            });

            uploadSession.AddPart(response.ETag);
        }
Ejemplo n.º 2
0
 public async Task AbortMultipartUpload(MultipartUploadSession uploadSession)
 {
     if (!uploadSession.IsCompleted)
     {
         var key = uploadSession.SessionId.AsS3ObjectKey(uploadSession.FileKey);
         await _cephS3Client.AbortMultipartUploadAsync(_filesBucketName, key, uploadSession.UploadId);
     }
 }
Ejemplo n.º 3
0
        /// <summary>
        /// Fetch file for created session.
        /// </summary>
        /// <param name="sessionId">Session identifier.</param>
        /// <param name="templateCode">Element's template code.</param>
        /// <param name="fetchParameters">Fetch parameters.</param>
        /// <exception cref="InvalidTemplateException">Specified template code does not refer to binary element.</exception>
        /// <exception cref="InvalidFetchUrlException">Fetch URL is invalid.</exception>
        /// <exception cref="MissingFilenameException">Filename is not specified.</exception>
        /// <exception cref="ObjectNotFoundException">Session or template has not been found.</exception>
        /// <exception cref="SessionExpiredException">Specified session is expired.</exception>
        /// <exception cref="S3Exception">Error making request to S3.</exception>
        /// <exception cref="InvalidBinaryException">Binary does not meet template's constraints.</exception>
        /// <exception cref="FetchFailedException">Fetch request failed.</exception>
        /// <returns>Fetched file key.</returns>
        public async Task <string> FetchFile(Guid sessionId, int templateCode, FetchParameters fetchParameters)
        {
            if (!TryCreateUri(fetchParameters, out var fetchUri))
            {
                throw new InvalidFetchUrlException(
                          $"Fetch URI must be a valid absolute URI with '{Uri.UriSchemeHttp}' or '{Uri.UriSchemeHttps}' scheme");
            }

            MultipartUploadSession uploadSession = null;

            var(sessionDescriptor, _, expiresAt) = await _sessionStorageReader.GetSessionDescriptor(sessionId);  // Firstly ensure that specified session exists

            try
            {
                var(stream, mediaType) = await _fetchClient.FetchAsync(fetchUri);

                var fileMetadata = new GenericUploadedFileMetadata(fetchParameters.FileName, mediaType, stream.Length);
                uploadSession = await InitiateMultipartUploadInternal(sessionId, templateCode, fileMetadata, sessionDescriptor, expiresAt);
                await UploadFilePart(uploadSession, stream, templateCode);

                var fetchedFileKey = await CompleteMultipartUpload(uploadSession);

                return(fetchedFileKey);
            }
            catch (FetchResponseTooLargeException ex)
            {
                throw new InvalidBinaryException(templateCode, new BinaryTooLargeError(ex.ContentLength));
            }
            catch (FetchRequestException ex)
            {
                throw new FetchFailedException($"Fetch request failed with status code {ex.StatusCode} and content: {ex.Message}");
            }
            catch (HttpRequestException ex)
            {
                throw new FetchFailedException($"Fetch request failed: {ex.Message}");
            }
            catch (TimeoutRejectedException)
            {
                throw new FetchFailedException("Fetch request failed: request timeout exceeded");
            }
            catch (FetchResponseContentTypeInvalidException ex)
            {
                throw new FetchFailedException($"Fetch request failed: {ex.Message}");
            }
            finally
            {
                if (uploadSession != null)
                {
                    await AbortMultipartUpload(uploadSession);
                }
            }
        }
Ejemplo n.º 4
0
        public async Task <string> CompleteMultipartUpload(MultipartUploadSession uploadSession)
        {
            var uploadKey      = uploadSession.SessionId.AsS3ObjectKey(uploadSession.FileKey);
            var partETags      = uploadSession.Parts.Select(x => new PartETag(x.PartNumber, x.Etag)).ToList();
            var uploadResponse = await _cephS3Client.CompleteMultipartUploadAsync(
                new CompleteMultipartUploadRequest
            {
                BucketName = _filesBucketName,
                Key        = uploadKey,
                UploadId   = uploadSession.UploadId,
                PartETags  = partETags
            });

            uploadSession.Complete();

            if (SessionDescriptor.IsSessionExpired(uploadSession.SessionExpiresAt))
            {
                throw new SessionExpiredException(uploadSession.SessionId, uploadSession.SessionExpiresAt);
            }

            try
            {
                using (var getResponse = await _cephS3Client.GetObjectAsync(_filesBucketName, uploadKey))
                {
                    var memoryStream = new MemoryStream();
                    using (getResponse.ResponseStream)
                    {
                        getResponse.ResponseStream.CopyTo(memoryStream);
                        memoryStream.Position = 0;
                    }

                    using (memoryStream)
                    {
                        var sessionDescriptor = uploadSession.SessionDescriptor;
                        var elementDescriptor = uploadSession.ElementDescriptor;
                        EnsureFileContentIsValid(
                            elementDescriptor.TemplateCode,
                            elementDescriptor.Type,
                            elementDescriptor.Constraints.For(sessionDescriptor.Language),
                            memoryStream,
                            uploadSession.UploadedFileMetadata);
                    }

                    var metadataWrapper = MetadataCollectionWrapper.For(getResponse.Metadata);
                    var fileName        = metadataWrapper.Read <string>(MetadataElement.Filename);

                    var fileExtension = Path.GetExtension(fileName).ToLowerInvariant();
                    var fileKey       = Path.ChangeExtension(uploadSession.SessionId.AsS3ObjectKey(uploadResponse.ETag), fileExtension);
                    var copyRequest   = new CopyObjectRequest
                    {
                        ContentType       = uploadSession.UploadedFileMetadata.ContentType,
                        SourceBucket      = _filesBucketName,
                        SourceKey         = uploadKey,
                        DestinationBucket = _filesBucketName,
                        DestinationKey    = fileKey,
                        MetadataDirective = S3MetadataDirective.REPLACE,
                        CannedACL         = S3CannedACL.PublicRead
                    };
                    foreach (var metadataKey in getResponse.Metadata.Keys)
                    {
                        copyRequest.Metadata.Add(metadataKey, getResponse.Metadata[metadataKey]);
                    }

                    await _cephS3Client.CopyObjectAsync(copyRequest);

                    _uploadedBinariesMetric.Inc();

                    _memoryCache.Set(fileKey, new BinaryMetadata(fileName, getResponse.ContentLength), uploadSession.SessionExpiresAt);

                    return(fileKey);
                }
            }
            finally
            {
                await _cephS3Client.DeleteObjectAsync(_filesBucketName, uploadKey);
            }
        }