Cấp bậc tác giả:

DOTNET

Tạo ảnh thu nhỏ trong ASP.NET

Được viết bởi QuangIT ngày 06/02/2013 lúc 11:30 AM
Có nhiều cách thu ảnh hình ảnh, nhưng người ta hay sử dụng System.Drawing API để thu nhỏ hình ảnh trong ASP.net. Việc thu nhỏ hình ảnh, phải đảm bảo chất lượng ảnh, phương thức an toàn, đảm bảo hiệu suất hệ thống.
  • 0
  • 2818
Tải tệp tin: Click ở đây

Tạo ảnh thu nhỏ trong ASP.NET


Mục lục
1. Giới thiệu
2. Hình ảnh trong HTML
3. Điều chỉnh kích cỡ hình ảnh sử dụng System.Drawing
4. Caching hình ảnh
5. Kết luận

Tên bài viết: Hướng dẫn cách thu nhỏ ảnh trong ASP.net
Tác giả: Quang.IT
Cấp độ bài viết: Chưa đánh giá

1. Giới thiệu:
Có nhiều cách thu ảnh hình ảnh, nhưng người ta hay sử dụng System.Drawing API để thu nhỏ hình ảnh trong ASP.net. Việc thu nhỏ hình ảnh, phải đảm bảo chất lượng ảnh, phương thức an toàn, đảm bảo hiệu suất hệ thống. Để làm được như vậy, phải sử dụng bộ nhớ đệm(caching). Trong bài viết này, Tôi sẽ mô phỏng 1 giải pháp xây dựng nó.

thumbnail.jpg

2. Hình ảnh trong HTML
Việc hiển thị hình ảnh trong HTML thì quá là đơn giản, nhưng việc xây dựng hình ảnh thu nhỏ không thể được tạo ra bằng cách gửi các byte của hình ảnh thay đổi kích cỡ vào dòng phản hồi của trang.
Lưu ý:
Trên thực tế, điều này không phải là hoàn toàn chính xác nữa, bây giờ các trình duyệt hiện đại nhất cho phép nhúng các nguồn tài nguyên MIME64 mã hóa nhị phân trực tiếp vào trang bằng cách sử dụng giao thức “data:”.
Xem http://www.ietf.org/rfc/rfc2397.txt để biết thêm thông tin.

Để nhúng hình ảnh thay đổi kích cỡ vào một trang, những gì bạn thực sự làm là đặt một tag img trong HTML và đưa nó vào thuộc tính src đến handler luồng nhị phân của hình ảnh. Dưới đây là một xử lý đơn giản phục vụ hình ảnh có tên được truyền vào tham số chuỗi truy vấn p (mà không thay đổi kích thước nó):
Ví dụ 1: Serving hình ảnh từ một xử lý
  1. public class Thumbnail : IHttpHandler {
  2.     private Regex _nameValidationExpression = new Regex(@"^[\w/]");
  3.     public void ProcessRequest (HttpContext context) {
  4.         string photoName = context.Request.QueryString["p"];
  5.         if (_nameValidationExpression.IsMatch(photoName)) {
  6.             throw new HttpException(404, "Invalid photo name.");
  7.         }
  8.         string photoPath = context.Server.MapPath("~/Photo/" + photoName + ".jpg");
  9.         context.Response.ContentType = "image/jpeg";
  10.         context.Response.WriteFile(photoPath);
  11.     }
  12.     public bool IsReusable {
  13.         get { return true; }
  14.     }
  15. }

Sử dụng handler cũng đơn giản như viết tag img như sau:
<img src="Thumbnail.ashx?p=copenhagen" alt="Copenhagen" />

Một điều cần lưu ý ở đây là xử lý bắt đầu bằng cách chứng thực tham số p người dùng nhập vào là điều không thể, do đó, chỉ cần xác nhận nó. Ở đây, chúng ta đang sử dụng một danh sách trắng, từ chối bất cứ điều gì không phải là văn tự, một chữ số, gạch dưới hoặc một dấu gạch chéo. Điều này có vẻ rất nghiêm ngặt, nhưng các danh sách trắng là theo định nghĩa an toàn hơn so với danh sách đen: nếu bạn liệt kê những gì bạn loại bỏ, bạn cần phải biết tất cả các cuộc tấn công tiềm năng, trong khi đó nếu bạn liệt kê những gì bạn chấp nhận bạn chỉ cần xác định một tập hợp các ký tự vô hại . Ở đây, chúng ta chỉ cho phép các tập tin JPEG theo hình ảnh thư mục con của trang web. Các ký tự dấu chấm là một ví dụ tốt của ký tự mà chúng ta muốn loại trừ vì nó có thể cho phép kẻ tấn công có được quyền truy cập vào thư mục gốc, nhưng có thể có những người khác, thoát khỏi phiên bản, v...v
handler làm cho đơn giản là thiết lập kiểu nội dung đến JPEG và viết ra nội dung của các tập tin trực tiếp vào luồng phản hồi.
3. Thay đổi kích thước một hình ảnh bằng cách sử dụng System.Drawing
Để có được một hình ảnh thu nhỏ của hình ảnh, tất cả chúng ta cần làm là sử dụng các API rất thuận tiện mà System.Drawing cung cấp. Nhưng trước tiên, chúng ta cần phải xác định kích thước của hình thu nhỏ. Để làm điều này, chúng ta phải xác định xem hình ảnh ban đầu có định dạng phong cảnh hoặc chân dung. Trong cả hai trường hợp, thu nhỏ cần để phù hợp với một hình vuông có kích thước được xác định trước. Trong trường hợp của bức chân dung, chiều cao là kích thước này được xác định trước, trong trường hợp của cảnh quan là chiều rộng. Các kích thước khác phải được giảm với tỷ lệ tương tự.

Ví dụ 2: Xác định kích thước hình ảnh thu nhỏ
  1. int thumbnailSize = 300;
  2. Bitmap photo = new Bitmap(photoPath);
  3. int width, height;
  4. if (photo.Width > photo.Height) {
  5.     width = thumbnailSize;
  6.     height = photo.Height * thumbnailSize / photo.Width;
  7. }
  8. else {
  9.     width = photo.Width * thumbnailSize / photo.Height;
  10.     height = thumbnailSize;
  11. }
Lưu ý:
Có vẻ như có một số tiềm ẩn để tràn số nguyên, nhưng trừ khi hình ảnh của bạn thực sự rất lớn, điều đó là khá an toàn.

Kích thước hình ảnh thu nhỏ nên được ấn định trước bởi nhà phát triển ứng dụng từ một hằng số hoặc từ cấu hình sẵn, nhưng không phải được đọc từ một chuỗi truy vấn hoặc người dùng cung cấp tham số vì đó sẽ cho phép cache-lượt tấn công mà một người sử dụng độc hại sẽ gửi yêu cầu thu nhỏ rất lớn hoặc cho một số lượng lớn các kích cỡ khác nhau.
Một giải pháp thay thế để tạo ra một phiên bản nhỏ hơn của hình ảnh với tỷ lệ tương tự như chúng ta đang làm ở đây là cắt hình ảnh thành một hình ảnh thu nhỏ hình vuông như Flickr. Điều này là khá đơn giản, và tôi sẽ không đi vào các chi tiết về làm thế nào để làm điều này, nhưng dự án mã đi kèm với bài viết này có chứa một phiên bản khác của trình xử lý, SquareThumbnail.ashx.
Một khi điều này được thực hiện, thực sự tạo ra giảm hình ảnh là một vấn đề kêu gọi các API phải đúng với các thông số. Bạn có thể dễ dàng có được các hình thu nhỏ xấu xí trong một dòng mã, chúng ta sẽ làm điều đó, nhưng với chất lượng tuyệt vời. Để làm điều đó, chúng ta chọn chất lượng cao bicubic như các thuật toán thay đổi kích thước và PNG như là định dạng cho đầu ra. Bài viết sau đây biện minh cho sự lựa chọn này:

InterpolationMode và CompositingQuality sử dụng để tạo hình thu nhỏ thông qua System.Drawing

Ví dụ 3: Xây dựng các bitmap thay đổi kích thước
  1. Bitmap target = new Bitmap(width, height);
  2. using (Graphics graphics = Graphics.FromImage(target))
  3. {
  4.     graphics.CompositingQuality = CompositingQuality.HighSpeed;
  5.     graphics.InterpolationMode = InterpolationMode.HighQualityBicubic;
  6.     graphics.CompositingMode = CompositingMode.SourceCopy;
  7.     graphics.DrawImage(photo, 0, 0, width, height);
  8.     using (MemoryStream memoryStream = new MemoryStream()) {
  9.         target.Save(memoryStream, ImageFormat.Png);
  10.         memoryStream.WriteTo(context.Response.OutputStream);
  11.     }
  12. }

Ở đây, chúng ta không gửi các luồng thay đổi kích thước trực tiếp vào dòng đầu ra bởi vì việc thực hiện PNG trong System.Drawing yêu cầu sử dụng luồng tìm kiếm, Response.OutputStream là không hợp lý. Đó là lý do tại sao chúng ta sử dụng một luồng bộ nhớ trung gian, làm tăng áp lực bộ nhớ, nhưng điều này sẽ được bù đắp bằng các bộ nhớ đệm hiệu quả mà tôi sẽ giới thiệu tiếp theo.
4. Bộ nhớ đệm hình ảnh(Caching)
Thay đổi kích thước hình ảnh, đặc biệt sử dụng một thuật toán tốt. Điều đầu tiên chúng ta có thể làm là thêm số lượng bộ nhớ đệm để xử lý:
Ví dụ 4: Đầu ra bộ nhớ đệm
  1. HttpCachePolicy cachePolicy = context.Response.Cache;
  2. cachePolicy.SetCacheability(HttpCacheability.Public);
  3. cachePolicy.VaryByParams["p"] = true;
  4. cachePolicy.SetOmitVaryStar(true);
  5. cachePolicy.SetExpires(DateTime.Now + TimeSpan.FromDays(365));
  6. cachePolicy.SetValidUntilExpires(true);
  7. cachePolicy.SetLastModified(lastModified);

Tùy thuộc vào bao nhiêu hình ảnh bạn giữ trên trang web và trên bộ nhớ bạn đã có sẵn trên máy chủ web. Nếu nó không phải, chúng ta có 1 mẹo, nhưng điều này sẽ chỉ làm việc trong một môi trường tin cậy cao hoặc đầy đủ (mà có thể là trong số các câu hỏi nếu trang web của bạn được lưu trữ trên máy hoặc vì lý do an ninh) hoặc nếu bạn biên dịch mã của bài viết này vào một dll đã đăng ký và triển khai nó vào GAC.
Những gì tôi muốn làm ở đây ngoài số lượng bộ nhớ đệm là bộ nhớ cache thu nhỏ hình trên đĩa rằng ngay cả khi bộ nhớ cache đầu ra hết hạn, chúng ta vẫn có thể phục vụ các phiên bản bộ nhớ cache đĩa nếu nó tồn tại thay vì thay đổi kích thước hình ảnh một lần nữa. Để làm điều đó, chúng ta cần một vị trí trên đĩa, nơi chúng ta đã viết quyền, tốt hơn mà không phải cấu hình ACL. Như vậy nó sẽ xảy ra tại một vị trí, và đó là các thế hệ mã thư mục cho các ứng dụng. Thư mục này nằm thuận tiện truy cập thông qua HttpRuntime.CodegenDir .
Viết thay đổi kích cỡ hình ảnh đến thư mục:
  1. string cachePath = Path.Combine(HttpRuntime.CodegenDir, photoName + ".png");
  2. using (FileStream diskCacheStream = new FileStream(cachePath, FileMode.CreateNew)) {
  3.     memoryStream.WriteTo(diskCacheStream);
  4. }
Kiểm tra sự sẵn có của phiên bản lưu trữ và gọi nó:
  1. if (File.Exists(cachePath)) {
  2.     context.Response.WriteFile(cachePath);
  3.     return;
  4. }
Điều này thực sự có ích vì chúng ta có ba cấp độ của bộ nhớ cache. Đầu tiên, trình duyệt lưu trữ các hình thu nhỏ cho một năm như vậy trong nhiều trường hợp máy chủ của bạn thậm chí không đạt. Thứ hai, IIS lưu trữ chúng trong bộ nhớ. Và cuối cùng, xử lý bộ nhớ cache đĩa riêng của mình để repopulate lần đầu tiên hay hai bất cứ khi nào chúng hết hạn. Điều này có nghĩa là mỗi bức ảnh có hiệu quả cần phải được thay đổi kích cỡ chỉ một lần. Bộ nhớ cache đĩa thậm chí có thể tồn tại một ứng dụng khởi động lại. Tất nhiên, đó cũng có nghĩa là nếu vì lý do gì cần phải được làm mới bộ nhớ cache, bạn sẽ cần phải tự làm và xóa các thư mục mã gen cho các ứng dụng, đó là hơi bất tiện nhưng là mức giá nhỏ để trả cho khả năng mở rộng sẽ nhận được từ phương thức này.
Làm sạch bộ nhớ cache đĩa có thể được thực hiện dễ dàng hơn nhiều bằng cách xây dựng bộ xử lý nhỏ, mà bạn không cần phải xác định vị trí các thư mục hệ mã. Tôi đã làm một bộ xử lý, DeleteCache.ashx , trong dự án tải về, nhưng phải cẩn thận để xử lý chỉ có thể truy cập đến một tài khoản quản trị.
Lưu ý:
Bộ nhớ đệm phía client sẽ ẩn các số truy cập vào các hình nhỏ từ số liệu thống kê của máy chủ web, vì vậy nếu nó quan trọng để nắm bắt tất cả các số liệu thống kê vào hình thu nhỏ bạn có thể muốn thay đổi chính sách bộ nhớ cache và loại bỏ cachePolicy.SetValidUntilExpires(true ).
5. Kết luận
Trong bài viết này, tôi đã hướng dẫn bạn làm thế nào để hiển thị các thumbnail chất lượng cao một cách an toàn và khả năng mở rộng.

Nguồn bài viết: Dngaz.com

BÌNH LUẬN BÀI VIẾT

Bài viết mới nhất

LIKE BOX

Bài viết được xem nhiều nhất

HỌC HTML