ในยุคดิจิตอลของวันนี้การจัดการภาพที่มีประสิทธิภาพเป็นสิ่งสําคัญสําหรับแอปพลิเคชันเว็บและ APIs หนึ่งในด้านหลักของการจัดการรูปภาพคือการบีบอัดซึ่งช่วยในการลดขนาดไฟล์โดยไม่ส่งผลกระทบอย่างมีนัยสําคัญต่อคุณภาพ คู่มือนี้จะช่วยให้คุณผ่านการสร้าง API แอมป์ภาพแบบไดนามิกโดยใช้ Aspose.Imaging สําหรับ .NET ในที่สุดคุณจะมี API Web Core ASP.NET ที่ใช้งานได้ซึ่งยอมรับภาพและส่งคืนผลผลิตที่แอมเพรสตามพารามิเตอร์คําถาม (รูปแบบคุณภาพการรีไซเคิลและอื่น ๆ )

Aspose.Imaging เป็นห้องสมุดที่มีประสิทธิภาพสําหรับการทํางานกับภาพใน .NET มันสนับสนุนรูปแบบหลายรูปแบบและให้คุณสมบัติการจัดการที่แข็งแกร่งรวมถึงการสูญเสีย (JPEG) และการทํางานที่ไม่มีการเสียหาย (PNG) เราจะใช้มันเพื่อสร้างบริการการบีบอัดที่มีประสิทธิภาพและสามารถปรับขนาดได้

สิ่งที่คุณจะสร้าง

  • *จุดสิ้นสุด *: POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
  • อินพุต: ไฟล์หลายส่วน (ภาพ) พารามิเตอร์การสอบถามตัวเลือกสําหรับรูปแบบ / คุณภาพ / ขนาด
  • ** Outputs**: กระแสภาพที่บีบอัดพร้อมกับที่ถูกต้อง Content-Type และหัว caching
  • ความปลอดภัย: การยืนยันประเภทเนื้อหาข้อ จํากัด ขนาดและ decode / encode ที่เก็บไว้

ข้อกําหนด

  • .NET 8 (หรือ .Net 6 +)
  • ASP.NET Core Web API โครงการ
  • หมายเลข: Aspose.Imaging
  • ตัวเลือก: การเปิดตัวใบอนุญาตในแอปพลิเคชันเริ่มต้น (ถ้าคุณใช้โครงสร้างที่ได้รับอนุญาโตตุลาการ)

โครงสร้างโครงการ (ขั้นต่ํา)

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

ตัวอย่างเต็มรูปแบบ (เซิร์ฟเวอร์ + ผู้ควบคุม)

เปลี่ยนพื้นที่ชื่อผู้ประกอบการด้วยพื้นที่ ชื่อของโครงการของคุณ

/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) ควบคุมการบีบอัดความเสียหาย
  • ข้อกําหนดของ PNG โดยปกติจะดีสําหรับรุ่นแรก หากคุณต้องการ P NG ขนาดเล็กพิเศษคุณสามารถเพิ่มการปรับปรุงขั้นสูงในภายหลัง
  • TryStripMetadata เป็นวิธีการที่ดีที่สุดที่พยายาม; APIs metadata แตกต่างกันตามรูปแบบแหล่งข้อมูล

/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 (DI การลงทะเบียน + ใบอนุญาตทางเลือก)

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

คู่มือขั้นตอน

ขั้นตอนที่ 1: สร้างโครงการ

สร้างโครงการ ASP.NET Core Web API ที่เพิ่ม Aspose.Imaging NuGet แพคเกจ สร้าง Models, Services, และ Controllers โพสต์ตามที่แสดงไว้ข้างต้น

ขั้นตอน 2: การตั้งค่า Aspose.Imaging (ใบอนุญาตทางเลือก)

หากคุณมีใบอนุญาตให้เริ่มต้นที่ startup (ดู Program.cs). นี้หลีกเลี่ยงการประเมินเครื่องหมายน้ําและให้แน่ใจว่าการทํางานอย่างสมบูรณ์

ขั้นตอนที่ 3: การดําเนินการบริการการบีบอัด

อะไร ImageCompressionService:

  • ดาวน์โหลดภาพผ่าน Image.Load(Stream)
  • ตัวเลือก strips metadata
  • ตัวเลือกการรีไซเคิลด้วยความสัมพันธ์ด้านที่เก็บรักษา
  • การประหยัด JPEG หรือ PNG ด้วยตัวเลือกที่เหมาะสมกับรูปแบบ

ขั้นตอน 4: สร้างตัวควบคุม API

ImageController แสดง POST /api/images/compress ใช้ไฟล์และคําถามพารามิเตอร์:

  • format: jpeg หรือ png (การกําหนดค่า jpeg)
  • quality: 1-100 (JPEG เท่านั้น; default 80)
  • maxWidth/maxHeight: ข้อ จํากัด สําหรับการลดลง
  • stripMetadataหมายเลขรุ่น: default true สําหรับการผลิตขนาดเล็ก

ขั้นตอน 5: การทดสอบ API

ใช้ลูกค้า HTTP ใด ๆ เพื่อส่ง multipart/form-data คําขอที่มีฟิลด์ไฟล์เดียวที่เรียกว่า file, plus ตัวเลือกคําถามพารามิเตอร์ ตรวจสอบ:

  • Response Content-Type รูปแบบการแข่งขัน
  • ขนาดไฟล์ที่กลับมาจะลดลง
  • การดําเนินการตามที่คาดหวัง

การเลือกการออกแบบและการปฏิบัติที่ดีที่สุด

  • การตั้งค่าข้อมูลแบบฟอร์ม: JPEG ใช้ Quality; PNG ยังคงไม่มีการสูญเสียสําหรับการผลิตที่คาดการณ์ได้
  • Downscale ก่อนที่เข้ารหัส: การรีไซเคิลลดพิกเซลครั้งแรก (ขนาดใหญ่ที่สุดชนะ) จากนั้นรหัสสกรูบิตเพิ่มเติม
  • การทําความสะอาดป้อนข้อมูล: ประเภทเนื้อหาบันทึกขนาดไฟล์ขอบเขตการสอบถาม
  • ** Streaming**: หลีกเลี่ยงการอ่านไฟล์ทั้งหมดลงในหน่วยความจําอย่างต่อเนื่อง ช่วยให้การไหลเป็นระยะสั้นและสามารถค้นหาได้
  • Caching: คํานวณการตอบสนองเป็นไม่เปลี่ยนแปลงถ้าคุณได้รับชื่อ / เนื้อหาจากป้อนข้อมูลที่กําหนดเอง; ในทางอื่น ๆ ปลั๊กหัว cache ไปยังกรณีการใช้ของคุณ
  • ความปลอดภัย: ตรวจสอบประเภทเนื้อหาและปฏิเสธค่าธรรมเนียมที่น่าสงสัย โปรดพิจารณาการสแกนสําหรับภาพที่ผิดปกติ
  • การสังเกตได้: ขนาดการบันทึกก่อน / หลังจากและพารามิเตอร์ที่ใช้ ซึ่งจะช่วยให้คุณแก้ไขข้อกําหนด
  • การหลอกลวง: หากถูกเปิดเผยโดยสาธารณะอัตรา จํากัด หรือต้องการ auth เพื่อป้องกันการละเมิด

ความยืดหยุ่นทั่วไป ( drop-in later)

  • การเข้ารหัส WebP/AVIF สําหรับภาพขนาดเล็ก (เพิ่มตัวเลือกใหม่/contentType/ไฟล์ขยายใน BuildOptions).
  • PNG tuning (ระดับกรอง / การบีบอัด) ถ้าคุณต้องการสินทรัพย์ที่ไม่เสียหายขนาดเล็กพิเศษ
  • การตั้งค่าโปรไฟล์ เช่น thumbnail, preview, hires แผนที่ไปยังพารามิเตอร์ที่รู้จัก
  • ** ETags** หรือเนื้อหา hashing เพื่อให้บริการตอบสนองที่คล้ายกันจาก cache
  • Async batch endpoint เพื่อบีบอัดไฟล์หลายไฟล์ในเวลาเดียวกัน

Troubleshooting

  • อินพุตขนาดใหญ่: เพิ่มขึ้น RequestSizeLimit หรือ Stream ไปยัง temp การจัดเก็บ
  • สีส้ม: พื้นที่สีที่มั่นใจจะได้รับการจัดการโดย default; กรณีขั้นสูงอาจต้องการประเภทสีอย่างชัดเจน
  • ไม่มีการลดขนาด (PNG): PNG ไม่ได้สูญเสีย อนุญาตให้รีไซเคิลหรือเปลี่ยนเป็น JPEG สําหรับการประหยัดไบต์ที่แข็งแกร่งมากขึ้น

คําอธิบาย

ตอนนี้คุณมี API การบีบอัดภาพแบบไดนามิกพร้อมการผลิตโดยใช้ Aspose.Imaging ตัวควบคุมจัดการอัปโหลดและพารามิเตอร์ บริการใช้ความปลอดภัยคอมเพรสเซอร์แบบฟอร์มและรีไซเคิลทางเลือกจากนั้นส่งกลับการตอบสนองที่กําหนดเองด้วยหัว cache จากที่นี่คุณสามารถเพิ่มรูปแบบเพิ่มเติมการตั้งค่าและกลยุทธ์ caching เพื่อให้เหมาะกับ stack ของเว็บของคุณ

More in this category