Browse Source

Fix serialization issue for uploading app image.

pull/419/head
Sebastian Stehle 6 years ago
parent
commit
66addb637a
  1. 23
      src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs
  2. 5
      src/Squidex.Domain.Apps.Entities/Apps/Commands/UploadAppImage.cs
  3. 53
      src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs
  4. 20
      src/Squidex.Web/FileExtensions.cs
  5. 2
      src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs
  6. 4
      src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs
  7. 8
      tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppCommandMiddlewareTests.cs

23
src/Squidex.Domain.Apps.Entities/Apps/AppCommandMiddleware.cs

@ -42,14 +42,7 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
if (context.Command is UploadAppImage uploadImage)
{
var image = await assetThumbnailGenerator.GetImageInfoAsync(uploadImage.File());
if (image == null)
{
throw new ValidationException("File is not an image.");
}
await assetStore.UploadAsync(uploadImage.AppId.ToString(), uploadImage.File(), true);
await UploadAsync(uploadImage);
}
await ExecuteCommandAsync(context);
@ -61,5 +54,19 @@ namespace Squidex.Domain.Apps.Entities.Apps
await next();
}
private async Task UploadAsync(UploadAppImage uploadImage)
{
var file = uploadImage.File;
var image = await assetThumbnailGenerator.GetImageInfoAsync(file.OpenRead());
if (image == null)
{
throw new ValidationException("File is not an image.");
}
await assetStore.UploadAsync(uploadImage.AppId.ToString(), file.OpenRead(), true);
}
}
}

5
src/Squidex.Domain.Apps.Entities/Apps/Commands/UploadAppImage.cs

@ -5,9 +5,8 @@
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using System;
using System.IO;
using Squidex.Domain.Apps.Core.Apps;
using Squidex.Infrastructure.Assets;
namespace Squidex.Domain.Apps.Entities.Apps.Commands
{
@ -15,6 +14,6 @@ namespace Squidex.Domain.Apps.Entities.Apps.Commands
{
public AppImage Image { get; set; }
public Func<Stream> File { get; set; }
public AssetFile File { get; set; }
}
}

53
src/Squidex.Domain.Apps.Entities/Assets/AssetCommandMiddleware.cs

@ -50,17 +50,14 @@ namespace Squidex.Domain.Apps.Entities.Assets
public override async Task HandleAsync(CommandContext context, Func<Task> next)
{
var tempFile = context.ContextId.ToString();
switch (context.Command)
{
case CreateAsset createAsset:
{
if (createAsset.Tags == null)
{
createAsset.Tags = new HashSet<string>();
}
await EnrichWithImageInfosAsync(createAsset);
await EnrichWithHashAndUploadAsync(createAsset, context);
await EnrichWithHashAndUploadAsync(createAsset, tempFile);
try
{
@ -68,32 +65,30 @@ namespace Squidex.Domain.Apps.Entities.Assets
foreach (var existing in existings)
{
if (IsDuplicate(createAsset, existing))
if (IsDuplicate(existing, createAsset.File))
{
var result = new AssetCreatedResult(existing, true);
context.Complete(result);
await next();
return;
}
}
foreach (var tagGenerator in tagGenerators)
{
tagGenerator.GenerateTags(createAsset, createAsset.Tags);
}
GenerateTags(createAsset);
await HandleCoreAsync(context, next);
var asset = context.PlainResult as IEnrichedAssetEntity;
var asset = context.Result<IEnrichedAssetEntity>();
context.Complete(new AssetCreatedResult(asset, false));
await assetStore.CopyAsync(context.ContextId.ToString(), createAsset.AssetId.ToString(), asset.FileVersion, null);
await assetStore.CopyAsync(tempFile, createAsset.AssetId.ToString(), asset.FileVersion, null);
}
finally
{
await assetStore.DeleteAsync(context.ContextId.ToString());
await assetStore.DeleteAsync(tempFile);
}
break;
@ -102,19 +97,19 @@ namespace Squidex.Domain.Apps.Entities.Assets
case UpdateAsset updateAsset:
{
await EnrichWithImageInfosAsync(updateAsset);
await EnrichWithHashAndUploadAsync(updateAsset, context);
await EnrichWithHashAndUploadAsync(updateAsset, tempFile);
try
{
await HandleCoreAsync(context, next);
var asset = context.PlainResult as IAssetEntity;
var asset = context.Result<IEnrichedAssetEntity>();
await assetStore.CopyAsync(context.ContextId.ToString(), updateAsset.AssetId.ToString(), asset.FileVersion, null);
await assetStore.CopyAsync(tempFile, updateAsset.AssetId.ToString(), asset.FileVersion, null);
}
finally
{
await assetStore.DeleteAsync(context.ContextId.ToString());
await assetStore.DeleteAsync(tempFile);
}
break;
@ -122,7 +117,6 @@ namespace Squidex.Domain.Apps.Entities.Assets
default:
await HandleCoreAsync(context, next);
break;
}
}
@ -139,9 +133,9 @@ namespace Squidex.Domain.Apps.Entities.Assets
}
}
private static bool IsDuplicate(CreateAsset createAsset, IAssetEntity asset)
private static bool IsDuplicate(IAssetEntity asset, AssetFile file)
{
return asset != null && asset.FileName == createAsset.File.FileName && asset.FileSize == createAsset.File.FileSize;
return asset?.FileName == file.FileName && asset.FileSize == file.FileSize;
}
private async Task EnrichWithImageInfosAsync(UploadAssetCommand command)
@ -149,14 +143,27 @@ namespace Squidex.Domain.Apps.Entities.Assets
command.ImageInfo = await assetThumbnailGenerator.GetImageInfoAsync(command.File.OpenRead());
}
private async Task EnrichWithHashAndUploadAsync(UploadAssetCommand command, CommandContext context)
private async Task EnrichWithHashAndUploadAsync(UploadAssetCommand command, string tempFile)
{
using (var hashStream = new HasherStream(command.File.OpenRead(), HashAlgorithmName.SHA256))
{
await assetStore.UploadAsync(context.ContextId.ToString(), hashStream);
await assetStore.UploadAsync(tempFile, hashStream);
command.FileHash = $"{hashStream.GetHashStringAndReset()}{command.File.FileName}{command.File.FileSize}".Sha256Base64();
}
}
private void GenerateTags(CreateAsset createAsset)
{
if (createAsset.Tags == null)
{
createAsset.Tags = new HashSet<string>();
}
foreach (var tagGenerator in tagGenerators)
{
tagGenerator.GenerateTags(createAsset, createAsset.Tags);
}
}
}
}

20
src/Squidex.Web/FileExtensions.cs

@ -0,0 +1,20 @@
// ==========================================================================
// Squidex Headless CMS
// ==========================================================================
// Copyright (c) Squidex UG (haftungsbeschraenkt)
// All rights reserved. Licensed under the MIT license.
// ==========================================================================
using Microsoft.AspNetCore.Http;
using Squidex.Infrastructure.Assets;
namespace Squidex.Web
{
public static class FileExtensions
{
public static AssetFile ToAssetFile(this IFormFile formFile)
{
return new AssetFile(formFile.FileName, formFile.ContentType, formFile.Length, formFile.OpenReadStream);
}
}
}

2
src/Squidex/Areas/Api/Controllers/Apps/AppsController.cs

@ -284,7 +284,7 @@ namespace Squidex.Areas.Api.Controllers.Apps
throw new ValidationException("Cannot create asset.", error);
}
return new UploadAppImage { File = file[0].OpenReadStream, Image = new AppImage(file[0].ContentType) };
return new UploadAppImage { File = file[0].ToAssetFile(), Image = new AppImage(file[0].ContentType) };
}
private static FileStream GetTempStream()

4
src/Squidex/Areas/Api/Controllers/Assets/AssetsController.cs

@ -313,9 +313,7 @@ namespace Squidex.Areas.Api.Controllers.Assets
throw new ValidationException("Cannot create asset.", error);
}
var assetFile = new AssetFile(formFile.FileName, formFile.ContentType, formFile.Length, formFile.OpenReadStream);
return assetFile;
return formFile.ToAssetFile();
}
}
}

8
tests/Squidex.Domain.Apps.Entities.Tests/Apps/AppCommandMiddlewareTests.cs

@ -69,7 +69,9 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var stream = new MemoryStream();
var command = CreateCommand(new UploadAppImage { AppId = appId, File = () => stream });
var file = new AssetFile("name.jpg", "image/jpg", 1024, () => stream);
var command = CreateCommand(new UploadAppImage { AppId = appId, File = file });
var context = CreateContextForCommand(command);
A.CallTo(() => assetThumbnailGenerator.GetImageInfoAsync(stream))
@ -86,7 +88,9 @@ namespace Squidex.Domain.Apps.Entities.Apps
{
var stream = new MemoryStream();
var command = CreateCommand(new UploadAppImage { AppId = appId, File = () => stream });
var file = new AssetFile("name.jpg", "image/jpg", 1024, () => stream);
var command = CreateCommand(new UploadAppImage { AppId = appId, File = file });
var context = CreateContextForCommand(command);
A.CallTo(() => assetThumbnailGenerator.GetImageInfoAsync(stream))

Loading…
Cancel
Save