Günümüzün dijital çağında, verimli görüntü yönetimi web uygulamaları ve APIs için çok önemlidir. Görüntü yönetiminin anahtar yönlerinden biri, dosya boyutlarını önemli ölçüde kaliteyi tehlikeye atmadan azaltmaya yardımcı olan kompresidir. Bu kılavuz, Aspose.Imaging için .NET kullanarak dinamik bir görüntüleme sıkıştırma API inşa etmenizi sağlar. Sonuçta, resimleri kabul eden ve sorgulama parametrelerine (format, kalite, yeniden yapılandırma ve daha fazlası) göre sıkışmış çıkışları geri getiren fonksiyonel bir ASP.NET Core Web API’ye sahip olacaksınız.

Aspose.Imaging, .NET’te resimlerle çalışmak için güçlü bir kütüphane. çok sayıda biçimi destekler ve kayıp (JPEG) ve kaybetme (PNG) çalışma akışları da dahil olmak üzere sağlam manipülasyon özellikleri sağlar.

Ne yapacaksın

  • Son nokta * : POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
  • Girişler: Çok parça dosya (resim), format / kalite / boyut için seçmeli sorgulama parametreleri
  • ** çıkışlar**: Doğru ile sıkıştırılmış görüntü akışı Content-Type Caching başlıkları
  • Güvenlik: İçerik tipi doğrulama, boyut sınırları ve kaydedilmiş dekod / kod

Ön koşullar

  • NET 8 (veya .NET 6+)
  • ASP.NET Core Web API Projesi
  • Nükleer : Aspose.Imaging
  • Seçmeli: uygulama başlangıcında lisans başlatma (lisanslı bir yapı kullanıyorsanız)

Proje Yapısı (Minimum)

/Controllers
  ImageController.cs
/Services
  ImageCompressionService.cs
/Models
  CompressionRequest.cs
Program.cs
appsettings.json

Tam Örnek (Service + Controller)

Yerleşim alanlarını projenizin adı alanı ile değiştirin.

/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) kayıp kompresyonu kontrol eder.
  • PNG varsayımları genellikle bir ilk versiyonu için iyi; eğer ekstra küçük png’lere ihtiyacınız varsa, daha sonra ileri tonlama ekleyebilirsiniz.
  • TryStripMetadata en iyi çaba yaklaşımıdır; metadata APIs kaynak biçimine göre değişir.

/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 (Devamını oku + seçmeli lisans)

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();

adım adım rehber

Adım 1: Projeyi hazırlayın

Bir ASP.NET Core Web API projesi oluşturun. Aspose.Imaging Yatırma paketini oluşturun. Models, Services, ve Controllers Yukarıda gösterildiği gibi dosyalar.

Adım 2: Aspose.Imaging ayarlayın (seçmeli lisans)

Eğer bir lisansınız varsa, başlangıçta başlatın (bkz. Program.csBu, değerlendirme su göstergelerinden kaçınır ve tam işlevselliği sağlar.

Adım 3: Kompresyon Hizmetini Uygulayın

The için ImageCompressionService:

  • Görüntüleri aracılığıyla Image.Load(Stream)
  • Opsiyonel Metadata Çıkarma
  • Optionally resizes with aspect ratio korunmuş bakış açısı ile
  • Format uygun seçeneklerle JPEG veya PNG’ye tasarruf

Adım 4: API Kontrolörü oluşturun

ImageController Gösteriler POST /api/images/compress Dosya ve sorgulama parametreleri:

  • format: jpeg veya png (Devamı için jpeg)
  • quality1 - 100 (yalnızca JPEG; varsayılan 80)
  • maxWidth/maxHeight• Düşük Kalınma Sınırları
  • stripMetadata• Default true Küçük üretim için

Adım 5: API testleri

Herhangi bir HTTP istemcisi göndermek için kullanın multipart/form-data tek bir dosya alanı ile talep file, artı seçmeli sorgulama parametreleri. kontrol edin:

  • Response Content-Type Maç Formatı
  • Geri gönderilen dosya boyutu azaldı
  • beklendiği gibi çalışmalarını yeniden başlatmak

Tasarım Seçenekleri ve En İyi Uygulamalar

  • Format uyarı ayarları: JPEG kullanır QualityPNG, tahmin edilebilir üretim için kayıtsız kalır.
  • Downscale önce kodlama: Resizing önce pikselleri azaltır (en büyük boyut kazanır), daha sonra kodlayarak kısaltma byte daha fazla.
  • Sanitize girişler: Muhafaza içeriği türü, dosya boyutu, sorgulama sınırları.
  • Streaming: Tüm dosyayı hafızaya tekrar tekrar okumaktan kaçının; akışları kısa ömürlü ve arama yapılabilir tutun.
  • Caching: Değerlendirici girişlerden ad / içerik çıkarırsanız değişmez cevapları işaretleyin; aksi takdirde cache başlıklarını kullanım durumunuza atın.
  • Güvenlik: İçerik türünü doğrulayın ve şüpheli ödeme yüklerini reddedin.
  • Görünürlük: Önceki/sonraki kayıt boyutları ve kullanılan parametreler; bu, varsayımları düzeltmenize yardımcı olur.
  • Trotling: Toplumsal olarak maruz kalırsa, kısıtlama veya kötüye kullanım önlemek için auth gerektirir.

Ortak uzantılar (drop-in daha sonra)

  • WebP/AVIF kodlayıcıları daha küçük resimler için (yeni seçenekler ekleyin/contentTypeDosya uzantısı içinde BuildOptions).
  • PNG tonlama (filtre / sıkıştırma seviyesi) ekstra küçük kayıp olmayan varlıklara ihtiyacınız varsa.
  • Önceden profilleri gibi thumbnail, preview, hires Bilinen parametrelere bakmak.
  • ETags veya cache’den benzer yanıtlar sunmak için içerik hashing.
  • Async batch endpoint aynı anda birden fazla dosyayı sıkıştırmak için.

Troubleshooting

  • Büyük girişler: artış RequestSizeLimit Ya da temp depolama için akış.
  • Renkler: Garanti renk alanı varsayılan olarak işlenir; gelişmiş durumlarda açık renk tipi gerekebilir.
  • Hiçbir boyut azaltma (PNG): PNG kayıtsızdır; daha güçlü byte tasarrufu için yeniden değiştirme veya JPEG’e geçme sağlar.

Özetle

Şimdi Aspose.Imaging’i kullanarak üretmeye hazır bir dinamik görüntü sıkıştırma API’sine sahip olursunuz. denetleyici yükleri ve parametreleri yönetir; hizmet güvenli, format-bilinçli kompresyonu ve seçmeli geri dönüşü uygular, daha sonra cache başlıkları ile düzgün bir cevap geri aktarır. buradan, web stack’inize uymak için daha fazla biçim, ön ayar ve caching stratejileri ekleyebilirsiniz.

More in this category