En l’era digital d’avui, el tractament eficient de la imatge és crucial per a les aplicacions web i APIs. Un dels aspectes clau de gestió de les imatges és la compressió, que ajuda a reduir les dimensions de fitxers sense comprometre significativament la qualitat. Aquest guia t’aconsegueix mitjançant la construcció d’una API de comprensió de imatge dinàmica utilitzant Aspose.Imaging per .NET. Al final, tindràs una API funcional ASP.NET Core Web que accepta imatges i torna la producció compresa segons els paràmetres de consulta (format, qualitat, resignació, i més).
Aspose.Imaging és una poderosa biblioteca per treballar amb les imatges en .NET. Suporta molts formats i proporciona característiques de manipulació robustes, incloent els fluxos de treball sense pèrdues (JPEG) i PNG. L’aprofitarem per construir un servei de compressió eficient i escalable.
Què construiràs
- El punt final *:
POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
- Inputs: arxiu multipart (imatge), paràmetres de consulta opcionals per al format / qualitat / mida
- Outputs: flux d’imatge comprès amb el correcte
Content-Type
Caps de càstig - Seguretat: validació del tipus de contingut, límits de mida i decode/encode guardat
Prerequisits
- .NET 8 (o .NET 6+)
- Projecte ASP.NET Core Web API
- El nou:
Aspose.Imaging
- Opcional: iniciació de llicència en la startup d’aplicacions (si vostè està utilitzant una construcció autoritzada)
Estructura del projecte (minimal)
/Controllers
ImageController.cs
/Services
ImageCompressionService.cs
/Models
CompressionRequest.cs
Program.cs
appsettings.json
Exemple complet (Service + Controller)
Substituïu els espais de nom del lloc amb el nom de l’espai del vostre projecte.
/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) controla la compressió de pèrdua.- Els defectes de PNG són normalment bons per a una primera versió; si vostè necessita pngs extra petits, pot afegir tuning avançat més tard.
TryStripMetadata
És un enfocament de millor esforç; les APIs de metadades varien segons el format font.
/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
(Registració + llicència opcional)
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();
Guia de pas a pas
Etapa 1: Establir el projecte
Creació d’un projecte ASP.NET Core Web API. Aspose.Imaging
El nou paquet. Crea el Models
, Services
, i Controllers
Els cartells com s’ha mostrat a dalt.
Pas 2: Configure Aspose.Imaging (llicència opcional)
Si teniu una llicència, inicieu-la a la startup (vegeu Program.cs
Això evita l’avaluació de les marques d’aigua i garanteix la plena funcionalitat.
Pas 3: Implementar el servei de compressió
The ImageCompressionService
:
- Carregar imatges a través
Image.Load(Stream)
- Opcionalment tria metadades
- Opcionalment resideix amb la proporció d’aspecte preservada
- Sorteig a JPEG o PNG amb opcions adequades al format
Pas 4: Construir el controlador d’API
ImageController
Exposició POST /api/images/compress
Fer un fitxer i query paràmetres:
format
:jpeg
opng
(defaultjpeg
)quality
1 - 100 (només JPEG; default 80)maxWidth
/maxHeight
Límits per a la descàrregastripMetadata
El defaulttrue
Per una producció més petita
Pas 5: Prova de l’API
Utilitza qualsevol client HTTP per enviar un multipart/form-data
Sol·licitud amb un sol camp de fitxers anomenat file
, a més de paràmetres de consulta opcional. Verificar:
- Response
Content-Type
El format dels partits - La mida del fitxer retornat es redueix
- Recuperar les obres com s’esperava
Seleccions de disseny i millors pràctiques
- Impostació de format-avís: JPEG utilitza
Quality
PNG es manté sense pèrdues per a la producció predictable. - Downscale abans de codificar: Recodificació redueix els píxels primer (el major grandària guanya), llavors codifica bit més endavant.
- Sanititza les entrades: Tipus de contingut de guàrdia, mida de fitxer, límits de consulta.
- Streaming: Eviteu llegir tot el fitxer a la memòria de manera repetida; mantingueu els fluxos curts de vida i buscables.
- Caching: Marca les respostes com a immutables si deriveu nom/contingut de les entrades deterministes; d’altra banda tuneu els encàrrecs de cache al cas de l’ús.
- Seguretat: Valida el tipus de contingut i rebutja càrregues de pagament sospitoses.
- Observabilitat: Dimensions de registre abans/després i paràmetres utilitzats; això t’ajuda a tonalitzar les defectes.
- Throttling: Si exposat públicament, límit de la taxa o requereix auth per prevenir l’abús.
Extensions comunes (drop-in més tard)
- WebP/AVIF codificadors per a imatges encara més petites (afegir noves opcions/
contentType
Extensions de fitxers enBuildOptions
). - PNG tuning (nivell de filtració/compressió) si vostè necessita actius extra petits sense pèrdues.
- Preseta els perfils com
thumbnail
,preview
,hires
Mapa de paràmetres coneguts. - ETags o hashing de continguts per servir les respostes idèntiques del cache.
- Async batxeta finalitza per compressar múltiples fitxers alhora.
Troubleshooting
- Molts ingressos: augmentar
RequestSizeLimit
o el flux a l’emmagatzematge temp. - Colors verdes: L’espai de colors assegurat es gestiona per defectes; els casos avançats poden necessitar un tipus de color explícit.
- No disminució de mida (PNG): PNG és sense pèrdues; permet la remissió o la transició a JPEG per a estalvis de byte més forts.
Resum
Ara vostè té una API de compressió d’imatge dinàmica preparada per a la producció utilitzant Aspose.Imaging. El controlador gestiona les carregades i els paràmetres; el servei s’aplica a compresssió segura, format-conscient i resissió opcional, llavors torna a fluir una resposta correctament tipificada amb capçalers de cache. D’aquí, pot afegir més formats, pre-sets i estratègies de cascament per adaptar-se a l’estac web.
More in this category
- Optimitzar els gifs animats en .NET utilitzant Aspose.Imaging
- Optimitzar TIFFs multipages per a l'arxiu en .NET amb Aspose
- Animacions de dades en .NET amb Aspose.Imaging
- Comparació Lossy vs. Lossless Image Compression en .NET utilitzant Aspose.Imaging
- Compressió d'imatge sense pèrdues i de qualitat en .NET amb Aspose.Imaging