Beispiel #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;
                BinaryValidationUtils.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);
        }
Beispiel #2
0
        public async Task <MultipartUploadSession> InitiateMultipartUploadInternal(
            Guid sessionId,
            int templateCode,
            IUploadedFileMetadata uploadedFileMetadata,
            SessionDescriptor sessionDescriptor,
            DateTime expiresAt)
        {
            if (string.IsNullOrEmpty(uploadedFileMetadata.FileName))
            {
                throw new MissingFilenameException($"Filename has not been provided for the item '{templateCode}'");
            }

            if (sessionDescriptor.BinaryElementTemplateCodes.All(x => x != templateCode))
            {
                throw new InvalidTemplateException(
                          $"Binary content is not expected for the item '{templateCode}' within template '{sessionDescriptor.TemplateId}' " +
                          $"with version Id '{sessionDescriptor.TemplateVersionId}'.");
            }

            var elementDescriptor = await GetElementDescriptor(sessionDescriptor.TemplateId, sessionDescriptor.TemplateVersionId, templateCode);

            BinaryValidationUtils.EnsureFileMetadataIsValid(elementDescriptor, sessionDescriptor.Language, uploadedFileMetadata);

            var fileKey = Guid.NewGuid().ToString();
            var key     = sessionId.AsS3ObjectKey(fileKey);
            var request = new InitiateMultipartUploadRequest
            {
                BucketName  = _filesBucketName,
                Key         = key,
                ContentType = uploadedFileMetadata.ContentType
            };
            var metadataWrapper = MetadataCollectionWrapper.For(request.Metadata);

            metadataWrapper.Write(MetadataElement.Filename, uploadedFileMetadata.FileName);

            var uploadResponse = await _cephS3Client.InitiateMultipartUploadAsync(request);

            return(new MultipartUploadSession(
                       sessionId,
                       sessionDescriptor,
                       expiresAt,
                       elementDescriptor,
                       uploadedFileMetadata,
                       fileKey,
                       uploadResponse.UploadId));
        }
Beispiel #3
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;
                        BinaryValidationUtils.EnsureFileContentIsValid(
                            elementDescriptor.TemplateCode,
                            elementDescriptor.Type,
                            elementDescriptor.Constraints.For(sessionDescriptor.Language),
                            memoryStream,
                            uploadSession.UploadedFileMetadata.FileName);
                    }

                    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, getResponse.Headers.ContentType), uploadSession.SessionExpiresAt);

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