public async Task <TPrimaryKey> CreateAsync(IFormFileCollection attachments, PostDto dto) { var isPostingAllowed = await _banService.IsPostingAllowedAsync(dto.ThreadId, dto.UserIpAddress); if (!isPostingAllowed.Item1) { throw new HttpResponseException(HttpStatusCode.Forbidden, isPostingAllowed.Item2); } else if (attachments == null) { return(await CreateAsync(dto, (post) => { post.Thread = Context.Threads.FirstOrDefault(thread => thread.Id == dto.ThreadId); })); } else { var postId = await CreateAsync(dto, (post) => { post.Thread = Context.Threads.FirstOrDefault(thread => thread.Id == dto.ThreadId); }); try { var containerName = dto.ThreadId.ToString(); if (string.IsNullOrWhiteSpace(containerName)) { throw new Exception($"{nameof(containerName)} is null or whitespace"); } foreach (var attachment in attachments) { string blobName; var attachmentParentDto = _attachmentCategorizer.CreateAttachmentDto(attachment.FileName); attachmentParentDto.PostId = postId; attachmentParentDto.FileExtension = Path.GetExtension(attachment.FileName)?.TrimStart('.'); attachmentParentDto.FileName = Path.GetFileNameWithoutExtension(attachment.FileName); attachmentParentDto.Size = attachment.Length; attachmentParentDto.Hash = _cryptoService.HashHex(attachment.OpenReadStream()); if (attachmentParentDto is AudioDto audioDto) { blobName = (await _audioService.CreateAsync(audioDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); } else if (attachmentParentDto is PictureDto pictureDto) { if (_attachmentCategorizer.IsPictureExtensionSupported(pictureDto.FileExtension)) { // generate thumbnail if such file extension is supported var image = Image.Load(attachment.OpenReadStream()); pictureDto.Width = image.Width; pictureDto.Height = image.Height; blobName = (await _pictureService.CreateAsync(pictureDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); var thumbnail = _thumbnailGenerator.GenerateThumbnail( image, _hikkabaConfiguration.ThumbnailsMaxWidth, _hikkabaConfiguration.ThumbnailsMaxHeight); await _storageProvider.SaveBlobStreamAsync( containerName + Defaults.ThumbnailPostfix, blobName, thumbnail.Image); } else { // otherwise save the same image as thumbnail blobName = (await _pictureService.CreateAsync(pictureDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); await _storageProvider.SaveBlobStreamAsync( containerName + Defaults.ThumbnailPostfix, blobName, attachment.OpenReadStream()); } } else if (attachmentParentDto is VideoDto videoDto) { blobName = (await _videoService.CreateAsync(videoDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); } else if (attachmentParentDto is DocumentDto documentDto) { blobName = (await _documentService.CreateAsync(documentDto, entity => { entity.Post = Context.Posts.FirstOrDefault(post => post.Id == postId); })).ToString(); } else { throw new Exception($"Unknown attachment type: {attachmentParentDto.GetType().Name}"); } if (string.IsNullOrWhiteSpace(blobName)) { throw new Exception($"{nameof(blobName)} is null or whitespace"); } await _storageProvider.SaveBlobStreamAsync(containerName, blobName, attachment.OpenReadStream()); } } catch (Exception ex) { _logger.LogError(ex + $" Post {postId} will be deleted."); await DeleteAsync(postId); throw; } return(postId); } }
private async Task CreateAttachmentsAsync(string containerName, Post postEntity, IFormFileCollection attachments) { foreach (var attachment in attachments) { var extension = Path.GetExtension(attachment.FileName)?.ToLowerInvariant()?.TrimStart('.'); var fileName = Path.GetFileNameWithoutExtension(attachment.FileName); var fileNameWithExtension = fileName + "." + extension; var attachmentParentDto = _attachmentCategorizer.CreateAttachmentDto(fileNameWithExtension); attachmentParentDto.PostId = postEntity.Id; attachmentParentDto.FileExtension = extension; attachmentParentDto.FileName = fileName; attachmentParentDto.Size = attachment.Length; attachmentParentDto.Hash = _cryptoService.HashHex(attachment.OpenReadStream()); string blobName; switch (attachmentParentDto) { case AudioDto audioDto: { var audioEntity = MapDtoToNewEntity <AudioDto, Audio>(audioDto); audioEntity.Post = postEntity; await _context.Audio.AddAsync(audioEntity); await _context.SaveChangesAsync(); blobName = audioEntity.Id.ToString(); break; } case PictureDto pictureDto: { if (_attachmentCategorizer.IsPictureExtensionSupported(pictureDto.FileExtension)) { using (var image = Image.Load(attachment.OpenReadStream())) { pictureDto.Width = image.Width; pictureDto.Height = image.Height; var pictureEntity = MapDtoToNewEntity <PictureDto, Picture>(pictureDto); pictureEntity.Post = postEntity; await _context.Pictures.AddAsync(pictureEntity); await _context.SaveChangesAsync(); blobName = pictureEntity.Id.ToString(); // generate thumbnail var thumbnail = _thumbnailGenerator.GenerateThumbnail( image, _hikkabaConfiguration.ThumbnailsMaxWidth, _hikkabaConfiguration.ThumbnailsMaxHeight); await _storageProvider.SaveBlobStreamAsync(containerName + Defaults.ThumbnailPostfix, blobName, thumbnail.Image); } } else { var pictureEntity = MapDtoToNewEntity <PictureDto, Picture>(pictureDto); pictureEntity.Post = postEntity; await _context.Pictures.AddAsync(pictureEntity); await _context.SaveChangesAsync(); blobName = pictureEntity.Id.ToString(); // save original image as thumbnail await _storageProvider.SaveBlobStreamAsync(containerName + Defaults.ThumbnailPostfix, blobName, attachment.OpenReadStream()); } break; } case VideoDto videoDto: { var videoEntity = MapDtoToNewEntity <VideoDto, Video>(videoDto); videoEntity.Post = postEntity; await _context.Video.AddAsync(videoEntity); await _context.SaveChangesAsync(); blobName = videoEntity.Id.ToString(); break; } case DocumentDto documentDto: { var documentEntity = MapDtoToNewEntity <DocumentDto, Document>(documentDto); documentEntity.Post = postEntity; await _context.Documents.AddAsync(documentEntity); await _context.SaveChangesAsync(); blobName = documentEntity.Id.ToString(); break; } default: throw new Exception($"Unknown attachment type: {attachmentParentDto.GetType().Name}"); } if (string.IsNullOrWhiteSpace(blobName)) { throw new Exception($"{nameof(blobName)} is null or whitespace"); } await _storageProvider.SaveBlobStreamAsync(containerName, blobName, attachment.OpenReadStream()); } }