Công nghệ - 13/05/2025 00:30:28
Xin chào các bạn, hôm nay, mình sẽ chia sẻ về một chủ đề thú vị và thực tiễn, website nào cũng phải áp dụng: Image Proxy – giúp tối ưu hóa việc xử lý hình ảnh trong các dự án webiste, đảm bảo hiệu suất, bảo mật và trải nghiệm người dùng tốt hơn.
Mình sẽ hướng dẫn cách triển khai Image Proxy bằng .NET, cũng như gợi ý một số mã nguồn mở mà bạn có thể sử dụng nhé. Bắt đầu thôi.
Image Proxy hiểu đơn giản một lớp trung gian (proxy) đứng giữa client (trình duyệt) và nguồn hình ảnh (image source). Nhằm mục đích
Trong bất kỳ một website nào, ngoài video, thì hình ảnh chiếm phần lớn băng thông và ảnh hưởng trực tiếp đến hiệu suất. Việc sử dụng Image Proxy sẽ giúp bạn cải thiện đáng kể trải nghiệm người dùng.
Hãy tưởng tượng bạn đang vận hành một website với hàng trăm bài viết, mỗi bài chứa nhiều hình ảnh. Nếu không có Image Proxy, bạn sẽ gặp các vấn đề sau:
Image Proxy giải quyết các vấn đề này bằng cách xử lý hình ảnh trước khi gửi đến client, đảm bảo hiệu suất và bảo mật.
Ở đây, mình sẽ sử dụng thư viện ImageSharp (`SixLabors.ImageSharp`) để xây dựng image proxy cho .net nhé. Đây là thư viện xử lý hình ảnh hiện đại, hỗ trợ đa nền tảng và có nhiều tính năng nâng cao.
Cài đặt các gói NuGet cần thiết:
dotnet add package SixLabors.ImageSharp
dotnet add package SixLabors.ImageSharp.Web
SixLabors.ImageSharp.Web là một middleware chuyên dụng để xử lý hình ảnh trong ASP.NET Core.
Trong Program.cs, thêm cấu hình cho ImageSharp:
using SixLabors.ImageSharp.Web.DependencyInjection;
var builder = WebApplication.CreateBuilder(args);
// Add ImageSharp services
builder.Services.AddImageSharp();
var app = builder.Build();
// Enable ImageSharp middleware
app.UseImageSharp();
app.MapGet("/", () => "Image Proxy is running!");
app.Run();
Tạo một endpoint để xử lý yêu cầu hình ảnh với ImageSharp:
using Microsoft.AspNetCore.Mvc;
using SixLabors.ImageSharp;
using SixLabors.ImageSharp.Formats.Webp;
using SixLabors.ImageSharp.Processing;
using System.Net.Http;
using System.Threading.Tasks;
[Route("api/image")]
[ApiController]
public class ImageProxyController : ControllerBase
{
private readonly HttpClient _httpClient;
public ImageProxyController(IHttpClientFactory httpClientFactory)
{
_httpClient = httpClientFactory.CreateClient();
}
[HttpGet]
public async Task<IActionResult> GetImage(string url, int? width, int? height, bool webp = false)
{
if (string.IsNullOrEmpty(url) || !Uri.TryCreate(url, UriKind.Absolute, out var uri))
{
return BadRequest("Invalid image URL.");
}
var response = await _httpClient.GetAsync(uri);
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode);
}
using var imageStream = await response.Content.ReadAsStreamAsync();
using var image = await Image.LoadAsync(imageStream);
// Resize if needed
if (width.HasValue || height.HasValue)
{
image.Mutate(x => x.Resize(new ResizeOptions
{
Size = new Size(width ?? image.Width, height ?? image.Height),
Mode = ResizeMode.Max
}));
}
// Convert to WebP if requested
using var outputStream = new MemoryStream();
if (webp)
{
await image.SaveAsync(outputStream, new WebpEncoder());
return File(outputStream.ToArray(), "image/webp");
}
await image.SaveAsJpegAsync(outputStream);
return File(outputStream.ToArray(), "image/jpeg");
}
}
Để tối ưu hiệu suất, bạn có thể tích hợp caching với MemoryCache hoặc Redis. Dưới đây là ví dụ với MemoryCache:
builder.Services.AddMemoryCache();
Sửa lại controller để sử dụng cache:
using Microsoft.Extensions.Caching.Memory;
[Route("api/image")]
[ApiController]
public class ImageProxyController : ControllerBase
{
private readonly HttpClient _httpClient;
private readonly IMemoryCache _cache;
public ImageProxyController(IHttpClientFactory httpClientFactory, IMemoryCache cache)
{
_httpClient = httpClientFactory.CreateClient();
_cache = cache;
}
[HttpGet]
public async Task<IActionResult> GetImage(string url, int? width, int? height, bool webp = false)
{
var cacheKey = $"{url}_{width}_{height}_{webp}";
if (_cache.TryGetValue(cacheKey, out byte[] cachedImage))
{
return File(cachedImage, webp ? "image/webp" : "image/jpeg");
}
if (string.IsNullOrEmpty(url) || !Uri.TryCreate(url, UriKind.Absolute, out var uri))
{
return BadRequest("Invalid image URL.");
}
var response = await _httpClient.GetAsync(uri);
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode);
}
using var imageStream = await response.Content.ReadAsStreamAsync();
using var image = await Image.LoadAsync(imageStream);
if (width.HasValue || height.HasValue)
{
image.Mutate(x => x.Resize(new ResizeOptions
{
Size = new Size(width ?? image.Width, height ?? image.Height),
Mode = ResizeMode.Max
}));
}
using var outputStream = new MemoryStream();
if (webp)
{
await image.SaveAsync(outputStream, new WebpEncoder());
}
else
{
await image.SaveAsJpegAsync(outputStream);
}
var imageBytes = outputStream.ToArray();
_cache.Set(cacheKey, imageBytes, TimeSpan.FromHours(1)); // Cache for 1 hour
return File(imageBytes, webp ? "image/webp" : "image/jpeg");
}
}
Trong template của website, sử dụng URL proxy thay cho URL gốc:
<img src="/api/image?
url=https://example.com/image.jpg&width=300&height=200&webp=true
" alt="Sample Image" />
Khi tích hợp Image Proxy vào website nói chung, CMS/blog của bạn nói riêng, bạn cần lưu ý:
<img src="/api/image?url=https://example.com/image.jpg&width=300"
srcset="/api/image?url=https://example.com/image.jpg&width=600 600w,
/api/image?url=https://example.com/image.jpg&width=300 300w"
sizes="(max-width: 600px) 300px, 600px"
alt="Sample Image" />
Thay vì tự viết từ đầu, bạn có thể sử dụng các thư viện hoặc dịch vụ mã nguồn mở để tiết kiệm thời gian và tận dụng cộng đồng hỗ trợ. Dưới đây là các giải pháp phù hợp cho dự án của bạn:
Image Proxy là một giải pháp mạnh mẽ để tối ưu hóa hình ảnh trong website, giúp cải thiện hiệu suất, bảo mật và trải nghiệm người dùng. Với .NET, bạn có thể tự xây dựng một Image Proxy đơn giản hoặc sử dụng thư viện như SixLabors.ImageSharp để có các tính năng nâng cao như nén, chuyển đổi định dạng WebP, và caching.
Trong các dự án website của mình, mình đã áp dụng Image Proxy với ImageSharp và thấy thời gian tải trang giảm đáng kể, đặc biệt trên thiết bị di động. Mình khuyến khích các bạn thử nghiệm và tùy chỉnh giải pháp này để phù hợp với nhu cầu của dự án.
Nếu bạn có câu hỏi hoặc muốn chia sẻ cách triển khai của mình, hãy để lại bình luận nhé! Đừng quên theo dõi blog để cập nhật thêm nhiều bài viết công nghệ thú vị.
Happy coding!
/Son Do - I share real-world lessons, team building & developer growth.
#ImageProxy #DotNet #ASPNetCore #WebDevelopment #TechBlog #ImageOptimization #Performance #WebP #SixLaborsImageSharp #CSharp #SoftwareEngineering #Coding #TechTips #NetDeveloper #Programming #WebPerformance #DeveloperLife #TechVietnam #1percentbetter #wecommit100xshare