Dalam era digital hari ini, pengendalian gambar yang efisien sangat penting untuk aplikasi web dan APIs. Salah satu aspek utama pengelolaan gambar adalah kompresi, yang membantu dalam mengurangi ukuran file tanpa secara signifikan mengganggu kualitas. panduan ini membimbing Anda melalui membangun API kompres foto yang dinamis menggunakan Aspose.Imaging untuk .NET. Pada akhirnya, Anda akan memiliki API Web ASP.NET Core yang berfungsi yang menerima gambar dan mengembalikan output yang dikompresi sesuai dengan parameter pertanyaan (format, kualitas, resing, dan banyak lagi).
Aspose.Imaging adalah perpustakaan yang kuat untuk bekerja dengan gambar dalam .NET. Ia mendukung banyak format dan menyediakan fitur manipulasi yang kukuh, termasuk kerugian (JPEG) dan aliran kerja tidak kalah (PNG). kami akan menggunakannya untuk membangun layanan kompresi yang efisien dan scalable.
Apa yang akan dibangun
- titik akhir :
POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
- titik akhir :
- Input: Multipart file (gambar), parameter pertanyaan pilihan untuk format/kualitas/resize
- ** outputs**: aliran gambar yang dikompresi dengan benar
Content-Type
dan caching headers - Keselamatan: Validasi jenis konten, batasan ukuran, dan dekode/encode yang disimpan
Persyaratan
- .NET 8 (atau .Net 6+)
- Proyek ASP.NET Core Web API
- Untuk NuGet:
Aspose.Imaging
- Optional: inisialisasi lisensi di aplikasi startup (jika Anda menggunakan bangunan berlesen)
Struktur proyek (minimum)
/Controllers
ImageController.cs
/Services
ImageCompressionService.cs
/Models
CompressionRequest.cs
Program.cs
appsettings.json
Contoh lengkap (Service + Controller)
Mengganti ruang nama pemegang tempat dengan area nama proyek Anda.
/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) mengontrol kompresi kerugian.- Default PNG biasanya bagus untuk versi pertama; jika Anda membutuhkan PNS yang lebih kecil, Anda dapat menambahkan tuning lanjutan kemudian.
TryStripMetadata
adalah pendekatan yang paling efisien; APIs metadata bervariasi berdasarkan format sumber.
/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
(Pendaftaran DI + lisensi pilihan)
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();
Panduan Langkah-Langkah
Langkah 1: Mengatur proyek
Mencipta proyek ASP.NET Core Web API. Aspose.Imaging
Pemasangan NuGet. membuat Models
, Services
, dan Controllers
seperti yang ditunjukkan di atas.
Langkah 2: Mengkonfigurasi Aspose.Imaging (lisensi pilihan)
Jika Anda memiliki lisensi, memulai di startup (lihat Program.cs
Ini menghindari penilaian indikator air dan memastikan fungsi penuh.
Langkah 3: Melaksanakan Layanan Kompresi
dan yang ImageCompressionService
:
- Mengunggah gambar melalui
Image.Load(Stream)
- Memilih Metadata Optional
- Optional resizes dengan aspect ratio disimpan
- Menyimpan ke JPEG atau PNG dengan opsi yang sesuai dengan format
Langkah 4: Membangun API Controller
ImageController
Eksposur POST /api/images/compress
Mengambil file dan query parameter:
format
:jpeg
ataupng
(dengan defaultjpeg
)quality
1 – 100 (hanya JPEG; default 80)maxWidth
/maxHeight
Batas untuk downscalingstripMetadata
dan defaulttrue
Untuk produksi yang lebih kecil
Langkah 5: Menguji API
Gunakan klien HTTP untuk mengirimkan multipart/form-data
Permintaan dengan satu file field yang disebut file
, plus parameter pertanyaan pilihan. periksa:
- Response
Content-Type
Format Pertandingan - Ukuran file yang dikembalikan dikurangi
- Mengembalikan kerja seperti yang diharapkan
Pilihan Desain & Praktik Terbaik
- Pengaturan format-aware*: menggunakan JPEG
Quality
PNG tetap kekurangan untuk hasil yang dapat diramalkan. - Downscale sebelum coding: Resizing mengurangi piksel terlebih dahulu (pemenang ukuran terbesar), kemudian menyulitkan byte lebih lanjut.
- Sanitize input: jenis konten yang disimpan, ukuran file, batas pertanyaan.
- Streaming: Hindari membaca seluruh file ke dalam memori berulang kali; menjaga aliran jangka pendek dan dapat dicari.
- Caching: Tanda respons sebagai tidak berubah jika Anda mengalir nama / konten dari input deterministik; jika tidak, tun headers cache ke kasus penggunaan Anda.
- Keselamatan: Validasi jenis konten dan menolak beban yang mencurigakan. pertimbangkan pemindaian untuk gambar yang rosak.
- Pengamatan: Ukuran log sebelum/selepas dan parameter yang digunakan; ini membantu Anda mengatur default.
- Trotling: Jika didedikasikan secara publik, batas tarif atau memerlukan auth untuk mencegah penyalahgunaan.
Perpanjangan umum (drop-in kemudian)
- Kode WebP/AVIF* untuk gambar yang lebih kecil (tambah opsi baru/
contentType
/ file extension dalamBuildOptions
). - PNG tuning (tingkat penapis/kompresi) jika Anda membutuhkan aset ekstra kecil tanpa kerugian.
- Predet profil seperti
thumbnail
,preview
,hires
Menghitung parameter yang diketahui. - Etag atau hashing konten untuk melayani respons yang sama dari cache.
- Async batch endpoint untuk mengkompresi beberapa file sekaligus.
Troubleshooting
- Pengeluaran yang besar: Meningkat
RequestSizeLimit
atau aliran untuk temp penyimpanan. - Wrong warna: Jaminan ruang warna diperlakukan oleh default; kasus lanjutan mungkin memerlukan jenis warna yang jelas.
- Tidak ada pengurangan ukuran (PNG): PNG tidak kalah; memungkinkan resize atau switch ke JPEG untuk simpanan byte yang lebih kuat.
Kesimpulannya
Anda sekarang memiliki API kompresi gambar dinamik yang siap produksi menggunakan Aspose.Imaging. Controller mengendalikan upload dan parameter; layanan memohon kompres yang aman, format-informasi dan resing optional, kemudian mengalir kembali respons yang dicetak dengan headers cache. Dari sini, Anda dapat menambahkan lebih banyak format, preset, dan strategi caching untuk menyesuaikan stack web Anda.
More in this category
- Mengoptimalkan GIF Animasi di .NET menggunakan Aspose.Imaging
- Mengoptimalkan Multi-Page TIFF untuk Archival dalam .NET dengan Aspose
- Animasi yang didorong data dalam .NET dengan Aspose.Imaging
- Gambar produk untuk platform e-commerce menggunakan Aspose.Imaging untuk .NET
- Kompresi gambar tanpa kerugian dan kualitas dalam .NET dengan Aspose.Imaging