У данашњој дигиталној ери, ефикасна обрада је од суштинског значаја за веб апликације и АПИ. Један од кључних аспеката управљања сликом је компресија, која помаже у смањењу величине датотеке без значајне компромиса на квалитет. Овај водич вас пролази кроз изградњу динамичке АПИ компакције слике користећи Асписе.Имање за .НЕТ. На крају ћете имати функционалну АСП.НЕт Цоре Веб АПС који прихвата слику и враћа компримовани излаз према параметрима претраге (формат, квалитета, ресинг и још много тога).
Aspose.Imaging je moćna knjižnica za rad sa slikama u .NET. podržava mnoge formate i pruža snažne funkcije manipulacije, uključujući gubitak (JPEG) i bez gubitaka (PNG) tokove rada.
Шта ћете изградити
- Крајња тачка * :
POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
- Крајња тачка * :
- Увод: Мултипартни датотека (слика), опционални параметри за претрагу за формат / квалитет / величину
- Излазе: компресирани поток слике са правилним
Content-Type
Кацхинг главе - Сигурност: валидација типа садржаја, ограничења величине и чувани декод / енкод
Принципи
- NET 8 (или .NET 6+)
- Пројекат ASP.NET Core Web API
- НУГЕТ :
Aspose.Imaging
- Опционално: иницијализација лиценце у апликацији за стартап (ако користите лиценцирани објекат)
Структура пројекта (минимално)
/Controllers
ImageController.cs
/Services
ImageCompressionService.cs
/Models
CompressionRequest.cs
Program.cs
appsettings.json
Потпуни пример (Сервис + Контролер)
Замените именоване просторе места са именом простора вашег пројекта.
/Models/CompressionRequest.cs
namespace ImageApi.Models;
public sealed class CompressionRequest
{
// "jpeg" or "png"
public string Format { get; init; } = "jpeg";
// 1..100 (applies to JPEG only; PNG is lossless)
public int? Quality { get; init; } = 80;
// Optional resize bounds; image is resized preserving aspect ratio if either is provided.
public int? MaxWidth { get; init; }
public int? MaxHeight { get; init; }
// If true, strip metadata (EXIF, IPTC) where applicable to reduce size further.
public bool StripMetadata { get; init; } = true;
// Guardrails
public void Validate()
{
var fmt = Format?.ToLowerInvariant();
if (fmt is not "jpeg" and not "png")
throw new ArgumentException("Unsupported format. Use 'jpeg' or 'png'.");
if (Quality is { } q && (q < 1 || q > 100))
throw new ArgumentException("Quality must be between 1 and 100.");
if (MaxWidth is { } w && w <= 0) throw new ArgumentException("MaxWidth must be positive.");
if (MaxHeight is { } h && h <= 0) throw new ArgumentException("MaxHeight must be positive.");
}
}
/Services/ImageCompressionService.cs
using Aspose.Imaging;
using Aspose.Imaging.ImageOptions;
using ImageApi.Models;
namespace ImageApi.Services;
public interface IImageCompressionService
{
Task<(MemoryStream output, string contentType, string fileExt)> CompressAsync(
Stream input, CompressionRequest req, CancellationToken ct = default);
}
public sealed class ImageCompressionService : IImageCompressionService
{
private readonly ILogger<ImageCompressionService> _logger;
public ImageCompressionService(ILogger<ImageCompressionService> logger)
{
_logger = logger;
}
public async Task<(MemoryStream output, string contentType, string fileExt)> CompressAsync(
Stream input, CompressionRequest req, CancellationToken ct = default)
{
req.Validate();
// Defensive copy to a seekable stream
var inbound = new MemoryStream();
await input.CopyToAsync(inbound, ct).ConfigureAwait(false);
inbound.Position = 0;
// Load image via Aspose.Imaging
using var image = Image.Load(inbound);
// Optional: strip metadata (where applicable)
if (req.StripMetadata)
{
TryStripMetadata(image);
}
// Optional resize (preserve aspect ratio)
if (req.MaxWidth.HasValue || req.MaxHeight.HasValue)
{
ResizeInPlace(image, req.MaxWidth, req.MaxHeight);
}
// Choose encoder and options
string fmt = req.Format.ToLowerInvariant();
var (options, contentType, ext) = BuildOptions(fmt, req.Quality);
// Save to output
var output = new MemoryStream();
image.Save(output, options);
output.Position = 0;
_logger.LogInformation("Compressed image to {Bytes} bytes as {Ext}", output.Length, ext);
return (output, contentType, ext);
}
private static void ResizeInPlace(Image image, int? maxW, int? maxH)
{
var w = image.Width;
var h = image.Height;
double scaleW = maxW.HasValue ? (double)maxW.Value / w : 1.0;
double scaleH = maxH.HasValue ? (double)maxH.Value / h : 1.0;
double scale = Math.Min(scaleW, scaleH);
if (scale < 1.0)
{
int newW = Math.Max(1, (int)Math.Round(w * scale));
int newH = Math.Max(1, (int)Math.Round(h * scale));
image.Resize(newW, newH);
}
}
private static (ImageOptionsBase options, string contentType, string ext) BuildOptions(string fmt, int? quality)
{
switch (fmt)
{
case "jpeg":
{
var q = quality ?? 80;
var jpeg = new JpegOptions { Quality = q };
return (jpeg, "image/jpeg", "jpg");
}
case "png":
{
// PNG is lossless; using defaults ensures broad compatibility.
// Many PNG tunables exist, but defaults are safe and effective.
var png = new PngOptions();
return (png, "image/png", "png");
}
default:
throw new ArgumentOutOfRangeException(nameof(fmt), "Unsupported format.");
}
}
private static void TryStripMetadata(Image image)
{
try
{
// Not every format exposes EXIF/IPTC the same way; a best-effort clear:
if (image is RasterImage raster)
{
raster.RemoveAllFonts();
raster.SetPropertyItems(Array.Empty<PropertyItem>());
}
}
catch
{
// Non-fatal; ignore if format doesn't support these operations
}
}
}
Notes
JpegOptions.Quality
(1-100) контролише губитак компресије.- ПНГ дефолти су обично фине за прву верзију; ако вам је потребан додатни мали ПНГ, можете додати напредни тунинг касније.
TryStripMetadata
је најбољи напор приступ; метадане АПИ варирају по изворном формату.
/Controllers/ImageController.cs
using ImageApi.Models;
using ImageApi.Services;
using Microsoft.AspNetCore.Mvc;
namespace ImageApi.Controllers;
[ApiController]
[Route("api/images")]
public sealed class ImageController : ControllerBase
{
private static readonly HashSet<string> AllowedContentTypes = new(StringComparer.OrdinalIgnoreCase)
{
"image/jpeg", "image/png", "image/gif", "image/webp", "image/bmp", "image/tiff"
};
private readonly IImageCompressionService _svc;
private readonly ILogger<ImageController> _logger;
public ImageController(IImageCompressionService svc, ILogger<ImageController> logger)
{
_svc = svc;
_logger = logger;
}
// POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
[HttpPost("compress")]
[RequestSizeLimit(25_000_000)] // 25 MB cap; adjust to your needs
public async Task<IActionResult> Compress(
[FromQuery] string? format,
[FromQuery] int? quality,
[FromQuery] int? maxWidth,
[FromQuery] int? maxHeight,
[FromQuery] bool stripMetadata = true,
IFormFile? file = null,
CancellationToken ct = default)
{
if (file is null || file.Length == 0)
return BadRequest("No file uploaded.");
if (!AllowedContentTypes.Contains(file.ContentType))
return BadRequest("Unsupported content type. Upload a common raster image (JPEG, PNG, GIF, WebP, BMP, TIFF).");
var req = new CompressionRequest
{
Format = string.IsNullOrWhiteSpace(format) ? "jpeg" : format!,
Quality = quality,
MaxWidth = maxWidth,
MaxHeight = maxHeight,
StripMetadata = stripMetadata
};
await using var input = file.OpenReadStream();
var (output, contentType, ext) = await _svc.CompressAsync(input, req, ct);
// Strong caching for immutable responses (tune for your app/CDN)
Response.Headers.CacheControl = "public,max-age=31536000,immutable";
return File(output, contentType, fileDownloadName: BuildDownloadName(file.FileName, ext));
}
private static string BuildDownloadName(string originalName, string newExt)
{
var baseName = Path.GetFileNameWithoutExtension(originalName);
return $"{baseName}-compressed.{newExt}";
}
}
Program.cs
(ИД регистрација + опционална лиценца)
using Aspose.Imaging;
using ImageApi.Services;
var builder = WebApplication.CreateBuilder(args);
// Optional: initialize Aspose license from a file or stream if you have one
// var license = new Aspose.Imaging.License();
// license.SetLicense("Aspose.Total.lic");
builder.Services.AddControllers();
builder.Services.AddEndpointsApiExplorer();
builder.Services.AddSwaggerGen();
builder.Services.AddSingleton<IImageCompressionService, ImageCompressionService>();
var app = builder.Build();
app.UseRouting();
app.UseAuthorization();
app.MapControllers();
// Enable for local testing
app.UseSwagger();
app.UseSwaggerUI();
app.Run();
Корак по корак водич
Корак 1: Поставите пројекат
Креирајте АСП.НЕТ Цоре Веб АПИ пројекат. Aspose.Imaging
Подешавање пакета. креирајте Models
, Services
, и Controllers
Списак као што је приказано горе.
Корак 2: Конфигурисати Аппосе.Имагинг (опционална лиценца)
Ако имате лиценцу, покрените је на стартапу (види Program.cs
Ово избегава евалуацију водених знакова и обезбеђује пуну функционалност.
Корак 3: Увођење услуге компресије
У том ImageCompressionService
:
- Преузмите слике преко
Image.Load(Stream)
- Опционално уклањају метадане
- Опционално рецизира са сачуваним односом аспекта
- Uštede na JPEG ili PNG sa opcijama koje odgovaraju formatu
Корак 4: Изградите АПИ контролер
ImageController
изложбе POST /api/images/compress
узимање датотеке и претраге параметара:
format
:jpeg
илиpng
(у подразумевањуjpeg
)quality
1 – 100 (само ЈПЕГ; дефолт 80)maxWidth
/maxHeight
Ограничења за спуштањеstripMetadata
• Дефолтtrue
Za manju proizvodnju
Корак 5: Тестирање АПИ-а
Користите било који ХТТП клијент да бисте послали multipart/form-data
Захтев са једним пољем датотеке именом file
, плус опционални параметри за претрагу. проверите:
- Response
Content-Type
Формат утакмице - Величина враћеног датотеке се смањује
- Повратак рада као што је очекивано
Дизајн избора и најбоље праксе
- Формат-овере подешавања: ЈПЕГ користи
Quality
PNG ostaje bez gubitaka za predvidljiv proizvod. - Downscale pre kodiranja: Resizing prvo smanjuje piksele (najveće veličine dobija), a zatim kodiranje kratke bajte dalje.
- Sanitize inputs: tip sadržaja za čuvanje, veličina datoteke, granice upitnika.
- Стреинг: Избегавајте читање целог датотеке у меморију поновљено; држите токове краткотрајним и траженим.
- Цацхинг: Маркирају одговоре као непроменљиве ако добијете име / садржај из детерминистичких уноса; у супротном тунирајте кеш наслове на ваш случај коришћења.
- Сигурност: Проверите тип садржаја и одбаците сумњиве плаћања. размотрите скенирање за погрешне слике.
- Observabilnost: Log veličine pre/posle i parametri korišteni; to vam pomaže da tune predviđanja.
- Троттинг: Ако је јавно изложена, лимит стопе или захтева аутх да би се спречило злоупотреба.
Уобичајене проширења (наставити касније)
- WebP/AVIF кодирачи за још мање слике (додајте нове опције/
contentType
Проширење датотеке уBuildOptions
). - ПНГ тунинг (ниво филтрирања/компресије) ако вам је потребан екстра мали имовина без губитка.
- ** Преузмите профиле** као
thumbnail
,preview
,hires
Истраживање познатих параметара. - Етаг или хашинг садржаја да служи идентичне одговоре из кеше.
- Async batch endpoint za komprimiranje više datoteka u jednom trenutku.
Troubleshooting
- Велики унос: повећање
RequestSizeLimit
или пребацивање у складиштење. - Борне боје: Обезбеђени боји се обрађују по подразумевању; напредни случајеви могу захтевати експлицитну врсту боја.
- Нема смањења величине (ПНГ): ПНГ је без губитака; омогућава повраћање или прелазак на ЈПЕГ за јаче штедње бита.
Резюме
Сада имате припремљену за производњу динамичку АПИ за компресију слике користећи Аспасе.Имагинг. Контролер управља преузимањима и параметрима; услуга се примењује безбедно, формат-оверивање и опционално рецидирање, а затим враћа правилно типиран одговор са кеш насловима. Овде можете додати више формата, пресета и кешинг стратегија да одговара вашем веб стаку.
More in this category
- Оптимизација анимираних ГИФ-а у .NET-у користећи Aspose.Imaging
- Оптимизирајте мулти-странице ТИФФ-а за архивирање у .NET-у са Асписом
- Анимације на основу података у .NET-у са Aspose.Imaging
- Бесплатна и квалитетно дефинисана компресија слике у .NET-у са аспозом.Имање
- Оптимизација високо резолуционих слика за мобилне и веб у .NET-у