V14: Resize url endpoint (#16275)

* Add image resizing endpoint

* Rename factory

* Actually use height and width

---------

Co-authored-by: nikolajlauridsen <nikolajlauridsen@protonmail.ch>
This commit is contained in:
Nikolaj Geisle
2024-05-14 10:42:33 +02:00
committed by GitHub
parent eda4a6cc55
commit d18bce0ea7
6 changed files with 215 additions and 0 deletions

View File

@@ -0,0 +1,13 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Web.Common.Authorization;
namespace Umbraco.Cms.Api.Management.Controllers.UrlSegment;
[VersionedApiBackOfficeRoute("imaging")]
[ApiExplorerSettings(GroupName = "Imaging")]
[Authorize(Policy = AuthorizationPolicies.BackOfficeAccess)]
public class ImagingControllerBase : ManagementApiControllerBase
{
}

View File

@@ -0,0 +1,32 @@
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Umbraco.Cms.Api.Management.Factories;
using Umbraco.Cms.Api.Management.ViewModels.Media;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.Services;
namespace Umbraco.Cms.Api.Management.Controllers.UrlSegment;
[ApiVersion("1.0")]
public class ResizeImagingController : ImagingControllerBase
{
private readonly IMediaService _mediaService;
private readonly IReziseImageUrlFactory _reziseImageUrlFactory;
public ResizeImagingController(IMediaService mediaService, IReziseImageUrlFactory reziseImageUrlFactory)
{
_mediaService = mediaService;
_reziseImageUrlFactory = reziseImageUrlFactory;
}
[MapToApiVersion("1.0")]
[HttpGet("resize/urls")]
[ProducesResponseType(typeof(IEnumerable<MediaUrlInfoResponseModel>), StatusCodes.Status200OK)]
public async Task<IActionResult> Urls([FromQuery(Name = "id")] HashSet<Guid> ids, int height = 200, int width = 200, ImageCropMode? mode = null)
{
IEnumerable<IMedia> items = _mediaService.GetByIds(ids);
return await Task.FromResult(Ok(_reziseImageUrlFactory.CreateUrlSets(items, height, width, mode)));
}
}

View File

@@ -16,6 +16,7 @@ internal static class MediaBuilderExtensions
builder.Services.AddTransient<IMediaEditingPresentationFactory, MediaEditingPresentationFactory>();
builder.Services.AddTransient<IUrlAssembler, DefaultUrlAssembler>();
builder.Services.AddTransient<IMediaUrlFactory, MediaUrlFactory>();
builder.Services.AddTransient<IReziseImageUrlFactory, ReziseImageUrlFactory>();
builder.Services.AddScoped<IAbsoluteUrlBuilder, DefaultAbsoluteUrlBuilder>();
builder.WithCollectionBuilder<MapDefinitionCollectionBuilder>().Add<MediaMapDefinition>();

View File

@@ -0,0 +1,9 @@
using Umbraco.Cms.Api.Management.ViewModels.Media;
using Umbraco.Cms.Core.Models;
namespace Umbraco.Cms.Api.Management.Factories;
public interface IReziseImageUrlFactory
{
IEnumerable<MediaUrlInfoResponseModel> CreateUrlSets(IEnumerable<IMedia> mediaItems, int height, int width, ImageCropMode? mode);
}

View File

@@ -0,0 +1,72 @@
using Microsoft.Extensions.Options;
using Umbraco.Cms.Api.Management.Routing;
using Umbraco.Cms.Api.Management.ViewModels.Media;
using Umbraco.Cms.Core.Configuration.Models;
using Umbraco.Cms.Core.Media;
using Umbraco.Cms.Core.Models;
using Umbraco.Cms.Core.PropertyEditors;
using Umbraco.Extensions;
namespace Umbraco.Cms.Api.Management.Factories;
public class ReziseImageUrlFactory : IReziseImageUrlFactory
{
private readonly IImageUrlGenerator _imageUrlGenerator;
private readonly ContentSettings _contentSettings;
private readonly MediaUrlGeneratorCollection _mediaUrlGenerators;
private readonly IAbsoluteUrlBuilder _absoluteUrlBuilder;
public ReziseImageUrlFactory(IImageUrlGenerator imageUrlGenerator, IOptions<ContentSettings> contentSettings, MediaUrlGeneratorCollection mediaUrlGenerators, IAbsoluteUrlBuilder absoluteUrlBuilder)
{
_imageUrlGenerator = imageUrlGenerator;
_contentSettings = contentSettings.Value;
_mediaUrlGenerators = mediaUrlGenerators;
_absoluteUrlBuilder = absoluteUrlBuilder;
}
public IEnumerable<MediaUrlInfoResponseModel> CreateUrlSets(IEnumerable<IMedia> mediaItems, int height, int width, ImageCropMode? mode)
{
return mediaItems.Select(media => new MediaUrlInfoResponseModel(media.Key, CreateUrls(media, height, width, mode))).ToArray();
}
private IEnumerable<MediaUrlInfo> CreateUrls(IMedia media, int height, int width, ImageCropMode? mode)
{
IEnumerable<string> urls = media
.GetUrls(_contentSettings, _mediaUrlGenerators)
.WhereNotNull();
return CreateThumbnailUrls(urls, height, width, mode);
}
private IEnumerable<MediaUrlInfo> CreateThumbnailUrls(IEnumerable<string> urls, int height, int width, ImageCropMode? mode)
{
foreach (var url in urls)
{
// Have to remove first char here, as it always contains the "."
var extension = Path.GetExtension(url).Remove(0, 1);
if (_imageUrlGenerator.SupportedImageFileTypes.InvariantContains(extension) is false)
{
continue;
}
var options = new ImageUrlGenerationOptions(url)
{
Height = height,
Width = width,
ImageCropMode = mode,
};
var relativeUrl = _imageUrlGenerator.GetImageUrl(options);
if (relativeUrl is null)
{
continue;
}
yield return new MediaUrlInfo
{
Culture = null,
Url = _absoluteUrlBuilder.ToAbsoluteUrl(relativeUrl).ToString(),
};
}
}
}

View File

@@ -10816,6 +10816,83 @@
]
}
},
"/umbraco/management/api/v1/imaging/resize/urls": {
"get": {
"tags": [
"Imaging"
],
"operationId": "GetImagingResizeUrls",
"parameters": [
{
"name": "id",
"in": "query",
"schema": {
"uniqueItems": true,
"type": "array",
"items": {
"type": "string",
"format": "uuid"
}
}
},
{
"name": "height",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 200
}
},
{
"name": "width",
"in": "query",
"schema": {
"type": "integer",
"format": "int32",
"default": 200
}
},
{
"name": "mode",
"in": "query",
"schema": {
"$ref": "#/components/schemas/ImageCropModeModel"
}
}
],
"responses": {
"200": {
"description": "Success",
"content": {
"application/json": {
"schema": {
"type": "array",
"items": {
"oneOf": [
{
"$ref": "#/components/schemas/MediaUrlInfoResponseModel"
}
]
}
}
}
}
},
"401": {
"description": "The resource is protected and requires an authentication token"
},
"403": {
"description": "The authenticated user do not have access to this resource"
}
},
"security": [
{
"Backoffice User": [ ]
}
]
}
},
"/umbraco/management/api/v1/indexer": {
"get": {
"tags": [
@@ -36709,6 +36786,17 @@
},
"additionalProperties": false
},
"ImageCropModeModel": {
"enum": [
"Crop",
"Max",
"Stretch",
"Pad",
"BoxPad",
"Min"
],
"type": "string"
},
"ImportDictionaryRequestModel": {
"required": [
"temporaryFile"