Jedan od ključnih aspekata upravljanja slikom je kompresija, koja pomaže u smanjenju veličine datoteke bez značajnog ugrožavanja kvalitete.Ovaj vodič vodi vas kroz izgradnju dinamičnog API za kompresiju slike pomoću Aspose.Imaging za .NET.U konačnici, imat ćete funkcionalni ASP.NET Core Web API koji prihvaća slike i vraća komprimiranu proizvodnju prema parametrima traženja (format, kvaliteta, recenzija i još mnogo toga).
Aspose.Imaging je moćna knjižnica za rad s slikama u .NET-u. podržava mnoge formate i pruža snažne funkcije manipulacije, uključujući gubitak (JPEG) i bez gubitaka (PNG) radne tokove.
Što ćete izgraditi
- Slijedeća stranica *:
POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
- Uvjeti: Multipart datoteka (slika), opcionalni parametri upitnika za format/kvalitet/resize
- Outputs: Komprimirani tok slike s ispravnim
Content-Type
i caching glave - Sigurnost: Validacija tipa sadržaja, ograničenja veličine i čuvani dekod/ekod
Preduzeća
- Sljedeći članakNET 8 (ili .NET 6+)
- ASP.NET Core Web API projekt
- Slijedeći :
Aspose.Imaging
- Opcionalno: inicijaliziranje licence u aplikaciji startup (ako koristite licenciranu zgradu)
Struktura projekta (minimalna)
/Controllers
ImageController.cs
/Services
ImageCompressionService.cs
/Models
CompressionRequest.cs
Program.cs
appsettings.json
Slijedeći članakSlužba + kontrolor (Service + Controller)
Zamijenite nazivne prostore domaćina s nazivnim prostorom vašeg projekta.
/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) kontrolira gubitak kompresije.- PNG predviđanja su obično dobra za prvu verziju; ako vam je potrebna dodatna mala pNG-a, kasnije možete dodati napredni tuning.
TryStripMetadata
To je najuspješniji pristup; API metapodataka varira po izvornom formatu.
/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
(Povijest o registraciji + opcionalna dozvola)
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();
korak po korak vodič
1. korak: postavite projekt
Stvorite ASP.NET Core Web API projekt. Aspose.Imaging
Slijedeći članakSvijet – Stvorite Models
, Services
, i Controllers
Podaci kao što su prikazani gore.
Korak 2: Konfigurirajte Aspose.Imaging (opcionalno licenciranje)
Ako imate licencu, inicijalizirajte ga na startu (vidjeti Program.cs
To izbjegava ocjenjivanje vodnih znakova i osigurava punu funkcionalnost.
Korak 3: Uvođenje usluge kompresije
Tko je ImageCompressionService
:
- Preuzimanje slika putem
Image.Load(Stream)
- Opcionalno strijati metapodatke
- Opcionalno oporavak sa sačuvanim aspektom
- Uštede na JPEG ili PNG s opcijama koje odgovaraju formatu
Korak 4: Izgradite API kontrolor
ImageController
izložbe POST /api/images/compress
uzimanje datoteke i parametara upitnika:
format
:jpeg
ilipng
(podrazumevanojpeg
)quality
1 – 100 (samo JPEG; podrazumevano 80)maxWidth
/maxHeight
Ograničenja za smanjenjestripMetadata
• defaulttrue
Za manju proizvodnju
Četvrti korak: testirati API
Koristite bilo koji HTTP klijenta za slanje multipart/form-data
zahtjev s jednim poljem datoteke nazvan file
, plus opcionalni parametri upitnika. provjerite:
- Response
Content-Type
Igra u formatu - Povratna veličina datoteke smanjena
- Preuzimanje radova kao što se očekivalo
Odabir dizajna i najbolje prakse
- Nastavitve osviještenosti o formatu: JPEG koristi
Quality
PNG ostaje bez gubitaka za predvidljiv proizvod. - Downscale prije kodiranja: Recodiranje najprije smanjuje piksele (najveća veličina dobiva), a zatim kodiranje kratke bajte dalje.
- Sanitizirajte ulaznice: Vrsta sadržaja za čuvanje, veličina datoteke, granice upitnika.
- Streaming: Izbjegavajte čitanje cijelog datoteke u memoriju više puta; zadržite struje kratkotrajne i tražive.
- Caching: Označite odgovore kao nepromjenjive ako izvučete ime/sadržaj iz determinističkih ulazaka; inače dodirnite naslovnice cache vašem slučaju korištenja.
- Sigurnost: Validirajte tip sadržaja i odbacite sumnjive plaćanja. razmislite o skeniranju za pogrešne slike.
- Observabilnost: Log veličine prije/poslije i parametri koji se koriste; to vam pomaže da tune predviđanja.
- Trotling: Ako je javno izložen, ograničiti stopu ili zahtijevati auth kako bi se spriječilo zlostavljanje.
Uobičajene proširenja (drop-in kasnije)
- WebP/AVIF koderi za još manju sliku (dodajte nove opcije/
contentType
Proširenje datoteke uBuildOptions
). - PNG tuning (na razini filtracije/kompresije) ako vam je potrebna dodatna sredstva bez gubitaka.
- Predstavite profile kao
thumbnail
,preview
,hires
Slijedeći članakZnati parametri. - ETags ili hashing sadržaja kako bi služili identičnim odgovorima iz cache-a.
- Async batch završna točka za komprimiranje više datoteka u jednom trenutku.
Troubleshooting
- Veliki ulaznici: povećanje
RequestSizeLimit
ili prijenos na temp skladištenje. - Bez boja: Sigurni prostor za boje obrađuje se podrazumevanjem; napredni slučajevi mogu zahtijevati izričitu vrstu boje.
- Nema smanjenja veličine (PNG): PNG je bez gubitaka; omogućuje ponovnu razmjenu ili prijelaz na JPEG za jače uštede bajta.
sažetak
Sada imate API za proizvodnju spremne za dinamičnu kompresije slike pomoću Aspose.Imaging. kontrolor upravlja uputama i parametrima; usluga se primjenjuje na sigurnu, formatu informiranu kompresiju i opcionalno ponavljanje, a zatim vraća ispravno tipiran odgovor s cache naslovnicama. Odatle možete dodati više formata, pre-seta i caching strategija kako bi se prilagodila vaš web stack.
More in this category
- Optimizacija animiranih GIF-a u .NET-u pomoću Aspose.Imaging
- Optimizacija multi-page TIFF-a za arhiviranje u .NET-u s Aspose-om
- Animacije na temelju podataka u .NET-u s Aspose.Imaging
- Bez gubitaka i kvalitetno definirana kompresija slike u .NET-u s Aspose.Imaging
- HEIC na JPEG/PNG Konverzija s Aspose.Imaging za .NET