در عصر دیجیتال امروز، مدیریت تصویر کارآمد برای برنامه های وب و APIs حیاتی است. یکی از جنبه های کلیدی مدیریت تصاویر فشرده سازی است، که به کاهش اندازه فایل بدون تضعیف قابل توجهی در کیفیت کمک می کند. این راهنمای شما را از طریق ساخت یک API فاش تصویر پویا با استفاده از Aspose.Imaging برای .NET راه می رود. در نهایت، شما یک ASP.NET Core Web API عملکردی خواهید داشت که تصاویر را می پذیرد و خروجی فاسد را با توجه به پارامترهای جستجو (فرمت، کیفیت، بازسازی و بیشتر) باز می گرداند.

Aspose.Imaging یک کتابخانه قدرتمند برای کار با تصاویر در .NET است که از بسیاری از فرمت ها پشتیبانی می کند و ویژگی های دستکاری قوی را فراهم می کنند، از جمله جریان های کاری از دست رفته (JPEG) و بدون زیان (PNG).

چه چیزی بسازید

    • نقطه نهایی : POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
  • ** واردات**: فایل چند قسمت (تصویر)، پارامترهای پرس و جو اختیاری برای فرمت / کیفیت / اندازه
  • ** خروجی ها**: جریان تصویر فشرده با صحیح Content-Type برچسب ها: caching headers
  • امنیت: اعتباربخشی نوع محتوا، محدودیت های اندازه و رمزگذاری ذخیره شده

پیش شرط

  • .NET 8 (یا .Net 6+)
  • نرم افزار ASP.NET Core Web API
  • نوکیا : Aspose.Imaging
  • اختیاری: شروع مجوز در اپلیکیشن استارتاپ (اگر شما از یک ساختمان مجاز استفاده می کنید)

ساختار پروژه (محدود)

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

نمونه کامل (Service + Controller)

جایگزین فضاهای نامی میزبان با فضای نام پروژه خود باشید.

/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 ۱ تا ۱۰۰) کنترل ضعف را کنترل می کند.
  • پیش فرض های PNG معمولا برای یک نسخه اول خوب است؛ اگر شما نیاز به پینگ های کوچک اضافی، شما می توانید اضافه کردن پیشرفته بعد از آن.
  • TryStripMetadata این یک رویکرد با بهترین تلاش است؛ APIs متا داده ها با توجه به فرمت منبع متفاوت است.

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

راهنمای گام به گام

مرحله اول: طرح را تنظیم کنید

ایجاد یک پروژه ASP.NET Core Web API. Aspose.Imaging بایگانی برچسب ها: ایجاد Models, Services, و Controllers پوشه ها همانطور که در بالا نشان داده شده است.

مرحله 2: تنظیم Aspose.Imaging (تولید مجوز اختیاری)

اگر شما یک مجوز دارید، آن را در استارتاپ شروع کنید (نگاه کنید به Program.csاین امر مانع از ارزیابی شاخص های آب می شود و عملکرد کامل را تضمین می کند.

مرحله سوم: استفاده از سرویس فشرده سازی

در این ImageCompressionService:

  • تصاویری از طریق Image.Load(Stream)
  • به صورت اختیاری متابولیسم را انتخاب کنید
  • به صورت اختیاری با نسبت ظاهر حفظ می شود.
  • صرفه جویی در JPEG یا PNG با گزینه های مناسب برای فرمت

مرحله 4: ایجاد کنترلر API

ImageController نمایشگاه ها POST /api/images/compress یک فایل و پارامترهای پرسشنامه:

  • format: jpeg یا png (به صورت پیش فرض jpeg)
  • quality: 1 تا 100 (فقط JPEG؛ پیش فرض 80)
  • maxWidth/maxHeight: محدودیت ها برای کاهش
  • stripMetadataفایرفاکس true برای تولید کمتری

مرحله پنجم: آزمایش آتش سوزی

استفاده از هر مشتری HTTP برای ارسال یک multipart/form-data درخواست با یک فیلد فایل نامیده می شود file، به علاوه پارامترهای پرس و جو اختیاری را بررسی کنید:

  • Response Content-Type بازی فرمت
  • حجم فایل بازگردانده شده کاهش می یابد
  • بازگرداندن کارهای پیش بینی شده

انتخاب طراحی و بهترین شیوه ها

  • ** تنظیمات آگاهی از فرمت**: استفاده از JPEG QualityPNG برای تولید قابل پیش بینی بدون زیان باقی می ماند.
  • Downscale قبل از رمزگذاری: بازگرداندن اولین پیکسل ها را کاهش می دهد (بزرگترین اندازه ها برنده می شوند) و سپس بایت های کوتاه را به کار می گیرد.
  • نمایش ورودی ها: نوع محتوای ذخیره، اندازه فایل، محدودیت های پرس و جو.
  • ترافیک: اجتناب از خواندن کل فایل به حافظه تکرار؛ نگه داشتن جریان کوتاه مدت و قابل جستجو.
  • Caching: اگر نام/محتویات را از ورودی های تعیین کننده به دست آورید، پاسخ های رمزگذاری ناپایدار را نشان می دهد؛ در غیر این صورت عنوان های ذخیره سازی را به مورد استفاده خود اضافه کنید.
  • امنیت: نوع محتوا را تأیید کنید و بار پرداخت مشکوک را رد کنید.در نظر گرفتن اسکن برای تصاویر نادرست.
  • ** قابل مشاهده**: اندازه های قبل و بعد از ثبت نام و پارامترهای مورد استفاده؛ این به شما کمک می کند تا تنظیمات پیش فرض را انجام دهید.
  • تلاش: در صورت قرار گرفتن در معرض عموم، محدودیت نرخ و یا نیاز به auth برای جلوگیری از سوءاستفاده.

گسترش های معمولی (بعد از آن)

  • WebP/AVIF رمزگذاری برای تصاویر حتی کوچکتر (به گزینه های جدید اضافه کنید/contentType/تمدید فایل در BuildOptions).
  • PNG tuning (درجه فیلتر / فشرده سازی) اگر شما نیاز به دارایی های کوچک اضافی بدون از دست دادن.
  • تصویب پروفایل ها مانند thumbnail, preview, hires از پارامترهای شناخته شده استفاده کنید.
  • ETags یا hashing محتوا برای پاسخ های یکسان از cache.
  • Async batch endpoint برای فشرده سازی چندین فایل به طور همزمان.

Troubleshooting

  • تولیدات بزرگ: افزایش RequestSizeLimit یا جریان به temp ذخیره سازی.
  • ** رنگ های روشن**: اطمینان از فضای رنگی با تنظیمات پیش فرض پردازش می شود؛ موارد پیشرفته ممکن است نیاز به نوع رنگ صریح داشته باشد.
  • بدون کاهش اندازه (PNG): PNG بدون از دست دادن است؛ امکان بازگشت یا تغییر به JPEG برای صرفه جویی در بایت قوی تر است.

خلاصه

شما در حال حاضر یک اپلیکیشن فشرده سازی تصویر پویا آماده تولید با استفاده از Aspose.Imaging. کنترلر مدیریت بارگذاری ها و پارامترها؛ سرویس اعمال می شود امن، فرمت-آگاهی و بازگرداندن اختیاری، پس از آن جریان بازگشت یک پاسخ به درستی تایپ شده با عنوان های مخفی. از اینجا، شما می توانید اضافه کردن بیشتر قالب ها، پیش تنظیمات، و استراتژی های خفیف برای مطابقت با صفحه وب خود را.

More in this category