如何通过Umbraco媒体服务保存事件获取图片宽高并验证比例
在Umbraco中上传前验证图片宽高比的实现方案
没问题,这个需求完全可以实现!你不用纠结直接把mediaItem转成Image类型,反而应该从上传的文件流入手来获取宽高——毕竟在保存事件触发时,媒体项可能还没真正写入磁盘,直接操作流更可靠。下面给你详细的实现步骤和代码示例:
核心思路
通过订阅Umbraco的MediaService.Saving事件,在媒体项保存前拦截上传的图片文件流,使用图片处理库读取宽高,再验证是否符合目标比例。推荐用ImageSharp(跨平台友好)来处理图片,避免System.Drawing.Common的平台限制问题。
具体实现步骤
1. 安装ImageSharp NuGet包
首先在项目中安装ImageSharp:
Install-Package SixLabors.ImageSharp # 或者用.NET CLI dotnet add package SixLabors.ImageSharp
2. 编写事件处理逻辑
创建一个Composer来注册媒体保存事件,然后在事件方法中完成宽高验证:
using Umbraco.Cms.Core.Composing; using Umbraco.Cms.Core.Events; using Umbraco.Cms.Core.Models; using Umbraco.Cms.Core.Services; using SixLabors.ImageSharp; using System.Linq; using System; public class ImageValidationComposer : IComposer { public void Compose(IUmbracoBuilder builder) { // 订阅媒体保存前的事件 builder.MediaService.Saving += MediaService_Saving; } private void MediaService_Saving(IMediaService sender, MediaSavingEventArgs e) { // 仅处理图片类型的媒体项(替换成你项目中的图片媒体类型别名,默认是"Image") const string imageMediaTypeAlias = "Image"; if (e.Media.ContentType.Alias != imageMediaTypeAlias) return; // 获取图片文件属性(默认的图片文件属性别名是"umbracoFile") var fileProperty = e.Media.Properties.FirstOrDefault(p => p.Alias == "umbracoFile"); if (fileProperty == null || fileProperty.Value == null) return; // 从属性中提取文件流 if (fileProperty.Value is IContentFile contentFile) { using var fileStream = contentFile.OpenStream(); // 读取图片宽高 using var image = Image.Load(fileStream); int imageWidth = image.Width; int imageHeight = image.Height; // 定义目标宽高比(示例:16:9) const double targetAspectRatio = 16.0 / 9.0; double actualAspectRatio = (double)imageWidth / imageHeight; // 允许一定的误差范围(比如±0.05,避免严格比例导致的用户困扰) const double tolerance = 0.05; if (Math.Abs(actualAspectRatio - targetAspectRatio) > tolerance) { // 取消保存操作并提示错误信息 e.Cancel = true; e.Message = $"图片宽高比不符合要求!当前比例为{imageWidth}:{imageHeight},需要接近16:9的比例"; } } } }
关键注意事项
- 媒体类型/属性别名:要确保代码中的
imageMediaTypeAlias和umbracoFile与你项目中的实际配置一致,如果自定义了媒体类型或属性,记得修改对应的别名。 - 版本兼容性:如果是Umbraco v8版本,
IContentFile的处理方式略有不同,你需要从MediaSavingEventArgs.Files集合中获取上传的文件流,示例代码可以调整为:if (e.Files.Any()) { var uploadedFile = e.Files.First(); using var stream = uploadedFile.OpenReadStream(); // 后续读取宽高的逻辑一致 } - 异常处理:实际项目中可以添加try-catch块,避免因损坏的图片文件导致事件崩溃。
内容的提问来源于stack exchange,提问作者luxor37
相关产品推荐
相关产品推荐

