Nykypäivän digitaalisessa iässä tehokas kuvankäsittely on välttämätöntä web-sovelluksille ja API:ille. Yksi tärkeimmistä näkökohdista kuvakäsittelyn on kompressi, joka auttaa vähentämään tiedostojen koon ilman huomattavaa vaarantaa laatua. Tämä opas ohjaa sinua rakentamalla dynaaminen kuva-kompressio API käyttämällä Aspose.Imaging for .NET. Lopulta sinulla on toimiva ASP.NET Core Web API, jolla hyväksyt kuvat ja palautetaan kompressoitu tuotto kyselyn parametrien (muoto, laatu, uudelleenkuvaaminen ja enemmän).
Aspose.Imaging on tehokas kirjasto kuvien kanssa .NET. Se tukee monia muotoja ja tarjoaa vahvoja manipulointiominaisuuksia, mukaan lukien tappio (JPEG) ja tappamaton (PNG) työnkulut.
Mitä rakennat
- Lopullinen kohde *:
POST /api/images/compress?format=jpeg&quality=75&maxWidth=1280&maxHeight=1280
- Inputs: Monikokoinen tiedosto (kuva), valinnaiset kyselyparametrit muotoon / laatuun / koon
- Outputs: Kompressiivinen kuvan virta oikealla
Content-Type
ja caching päälliköt - Turvallisuus: Sisällöntyyppinen validointi, koon rajoitukset ja säilytetty dekode/encode
edellytykset
- • .NET 8 (tai .Net 6+)
- ASP.NET Core Web API -hanke
- Ja nyt:
Aspose.Imaging
- Vaihtoehtoinen: lisenssin aloittaminen sovelluksen käynnistämisessä (jos käytät lisensoitua rakennetta)
Projektin rakenne (minimi)
/Controllers
ImageController.cs
/Services
ImageCompressionService.cs
/Models
CompressionRequest.cs
Program.cs
appsettings.json
Täydellinen esimerkki (Service + Controller)
Vaihda paikanhaltijan nimipaikat projektisi nimipisteellä.
/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) hallitsee tappion kompressiota.- PNG-vaatimukset ovat tyypillisesti hienoja ensimmäiselle versiolle; jos tarvitset ylimääräisiä pieniä pNG:itä, voit lisätä kehittyneitä tunteita myöhemmin.
TryStripMetadata
on parhaiten tehokas lähestymistapa; metadata APIs vaihtelevat lähdeformaatin mukaan.
/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
(Rekisteröinti + valinnainen lisenssi)
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();
Vaiheittainen opas
Vaihe 1: Suunnittele projekti
Luo ASP.NET Core Web API -hanke. Aspose.Imaging
Laajennettu paketti. luo Models
, Services
, ja Controllers
Käsikirjoja kuten edellä on kuvattu.
Vaihe 2: Aseta Aspose.Imaging (vaihtoehtoinen lisenssi)
Jos sinulla on lisenssi, aloita se startupissa (katso Program.cs
Tämä estää arvioinnin vesimerkkejä ja varmistaa täydellisen toiminnallisuuden.
Vaihe 3: Kompressiopalvelun toteuttaminen
Se on ImageCompressionService
:
- Lataa kuvia kautta
Image.Load(Stream)
- Vaihtoehtoisesti metatiedot
- Vaihtoehtoisesti kierrätys aspekti suhteessa säilytetty
- Säästää JPEG: lle tai PNG:lle muotoon sopivilla vaihtoehdoilla
Vaihe 4: Rakenna API-ohjain
ImageController
Näyttelyt POST /api/images/compress
Tiedosto ja kysely parametrit:
format
:jpeg
taipng
( oletusarvoinenjpeg
)quality
1–100 (vain JPEG; oletusarvo 80)maxWidth
/maxHeight
• rajat laskeutumiseenstripMetadata
• Defaulttitrue
Vähemmän tuotantoa
Vaihe 5: Testaa API
Käytä HTTP-klienttia lähettääksesi multipart/form-data
pyyntö yhdellä tiedoston kentällä nimeltään file
, plus valinnaiset kyselyparametrit. Tarkista:
- Response
Content-Type
Otteluformaatti - Palautetun tiedoston koko pienenee
- Työt toistetaan odotettua
Suunnitteluvaihtoehdot ja parhaat käytännöt
- Format-varmuuden asetukset: JPEG käyttää
Quality
PNG on ennustettavissa oleva tuotto. - Downscale ennen koodausta: Resizing vähentää pikselejä ensin (suurin koko voittaa), sitten koodat lyhennät bytejä edelleen.
- Sanitisaatiot: Säilytä sisältö tyyppi, tiedoston koko, kyselyn rajat.
- Streaming: Vältä koko tiedoston lukemista muistiin toistuvasti; pidä virrat lyhytaikaisia ja etsimättömiä.
- Caching: Markkaa vastaukset muuttumattomana, jos tuodaan nimen/sisällön deterministisista tuloksista; muutoin tunnistaa cache-päälliköt käytöstäsi.
- Turvallisuus: Valitse sisällön tyyppi ja hylkää epäilyttäviä maksuja.
- ** Huomaamattomuus**: Rekisteröinti ennen/ jälkeen ja käytetyt parametrit; tämä auttaa sinua tunnistamaan oletukset.
- Trotling: Jos julkisesti esitetään, korko-raja tai vaatii auth estääkseen väärinkäytön.
Yleiset laajennukset (drop-in myöhemmin)
- WebP/AVIF koodit vielä pienemmille kuville (lisätä uusia vaihtoehtoja/
contentType
/ tiedoston laajennusBuildOptions
). - PNG tuning (suodatus/kompressiotaso) jos tarvitset vähäisiä menetettömiä varoja.
- Lisää profiileja kuten
thumbnail
,preview
,hires
Tietyt parametrit tunnetaan tiedossa. - ETags tai sisällön hashing palvelemaan samankaltaisia vastauksia cache.
- Async batch endpoint kompressoi useita tiedostoja kerralla.
Troubleshooting
- Suuri tulos*: Lisääntyminen
RequestSizeLimit
tai virtaa temp tallennukseen.
- Suuri tulos*: Lisääntyminen
- Punainen väri: Varmista värivaihe on käsitelty oletusarvoilla; kehittyneet tapaukset saattavat vaatia nimenomaista värityyppiä.
- ** Ei koon vähennystä (PNG)**: PNG on häviämätön; mahdollistaa uudelleenmuodostuksen tai siirtymisen JPEG:een vahvempien bytin säästöjen vuoksi.
Yhteenveto
Nyt sinulla on tuotantoa valmiina dynaaminen kuvan kompressi API käyttämällä Aspose.Imaging. ohjaimen käsittelee latauksia ja parametreja; palvelu soveltaa turvallista, muoto-varmuus kompressio ja valinnainen uudelleenkäyttö, sitten virtaa takaisin asianmukaisesti kirjoitettu vastaus cache-päälliköt. Täältä voit lisätä enemmän muodoja, esityksiä ja caching strategioita sopii web stack.
More in this category
- Animoitujen GIF:ien optimointi .NET:ssä käyttämällä Aspose.Imaging
- Optimoi monivuotiset TIFF:t arkistointiin .NET: ssä Asposella
- E-kaupankäynnin alustojen tuotekuvia käyttämällä Aspose.Imaging for .NET
- HEIC JPEG/PNG muuntaminen Aspose.Imaging for .NET
- Korkean resoluution kuvien optimointi mobiilille ja webille .NET: ssä