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); }
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)); }
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); } }