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.csTo 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 ili png (podrazumevano jpeg)
  • quality1 – 100 (samo JPEG; podrazumevano 80)
  • maxWidth/maxHeightOgraničenja za smanjenje
  • stripMetadata• default true 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 QualityPNG 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/contentTypeProširenje datoteke u BuildOptions).
  • 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