2008-09-26 39 views
14

Cách tốt nhất để xử lý bộ nhớ đệm của hình ảnh bằng cách sử dụng PHP là gì.Cách tốt nhất để lưu hình ảnh được chỉnh lại kích thước bằng PHP và MySQL

Tên tệp hiện được lưu trữ trong cơ sở dữ liệu MySQL được đổi tên thành GUID khi tải lên, cùng với tên tệp và thẻ alt gốc.

Khi hình ảnh được đưa vào các trang HTML, nó được thực hiện để sử dụng url như '/images/get/200x200/{guid}.jpg được viết lại thành tập lệnh php. Điều này cho phép các nhà thiết kế của tôi chỉ định (khoảng - hình ảnh nguồn có thể nhỏ hơn) kích thước tệp.

Tập lệnh php sau đó tạo băm có kích thước (200x200 trong url) và tên tệp GUID và nếu tệp đã được tạo trước đó (tệp có tên băm tồn tại trong thư mục TMP) sẽ gửi tệp từ thư mục TMP ứng dụng. Nếu tên tệp băm không tồn tại, sau đó nó được tạo ra, ghi vào đĩa và được phục vụ theo cách tương tự,

Điều này có hiệu quả không? (Nó cũng hỗ trợ watermarking hình ảnh và các thiết lập watermarking được lưu trữ trong băm là tốt, nhưng thats ra khỏi phạm vi này.)

Trả lời

10

Có hai lỗi chính tả trong Dan Udey của viết lại ví dụ (và tôi không thể bình luận về nó), nó nên được thay :

RewriteCond %{REQUEST_URI} ^/images/cached/ 
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f 
RewriteRule (.*) /images/generate.php?$1 [L] 

Kính trọng.

+2

Cảm ơn, tôi đã cập nhật mã trong mỏ chỉ trong trường hợp họ sử dụng mã đó thay vì phiên bản cố định của bạn. –

0

Cách tiếp cận của bạn có vẻ khá hợp lý - Tôi sẽ thêm rằng một số cơ chế nên được đưa vào kiểm tra xem ngày phiên bản được lưu trong bộ nhớ cache đã được tạo ra sau dấu thời gian được sửa đổi lần cuối của tệp hình ảnh gốc (nguồn) và nếu không tạo lại phiên bản đã được lưu trữ/thay đổi kích thước. Điều này sẽ đảm bảo rằng nếu một hình ảnh được thay đổi bởi các nhà thiết kế, bộ đệm sẽ được cập nhật một cách thích hợp.

+0

Lời khuyên tốt, nhưng ... Nếu nguồn được thay đổi bằng hình ảnh mới được tải lên (thông qua giao diện quản trị) thì GUID mới sẽ được tạo và tên tệp được lưu trong bộ nhớ cache sẽ không còn khớp nữa. Hình ảnh không được tải lên bằng (s) FTP, nhưng tất cả chúng ta đều biết về các giả định. ;) Sẽ xem xét việc triển khai. –

+0

Tôi cũng kiểm tra xem hình ảnh đã được lưu vào bộ nhớ đệm hay chưa, tức là 'if (filemtime ($ cached_image)> filemtime ($ _ SERVER ['SCRIPT_FILENAME'])) {...}' –

0

Điều đó nghe có vẻ giống như một cách chắc chắn để thực hiện điều đó. Bước tiếp theo có thể vượt xa PHP/MySQL.

Có lẽ, tinh chỉnh tiêu đề của bạn:

Nếu bạn đang sử dụng PHP để gửi các loại MIME, bạn cũng có thể sử dụng 'Keep-alive' và 'Cache-control' tiêu đề để kéo dài tuổi thọ của hình ảnh của bạn trên máy chủ và lấy một số tải của PHP/MySQL.

Ngoài ra, hãy xem xét (các) plugin apache để lưu vào bộ nhớ đệm. Giống như mod_expires.

Ồ, một điều nữa, bạn có bao nhiêu quyền kiểm soát đối với máy chủ của mình? Chúng tôi có nên giới hạn cuộc hội thoại này thành chỉ PHP/MySQL không?

+0

Ứng dụng được lưu trữ trên một VPS, vì vậy tôi có quyền truy cập root. mod_expires được cài đặt, do đó, trông giống như một tinh chỉnh .htaccess đơn giản có thể làm giảm tải máy chủ một chút. Mẹo hay, cảm ơn. –

0

phpThumb là khuôn khổ tạo hình ảnh/hình thu nhỏ được thay đổi kích cỡ khi đang di chuyển. Nó cũng thực hiện bộ nhớ đệm và nó rất dễ thực hiện.

Các mã để thay đổi kích thước một hình ảnh là:

<img src="/phpThumb.php?src=/path/to/image.jpg&w=200&amp;h=200" alt="thumbnail"/> 

sẽ cung cấp cho bạn một hình ảnh thu nhỏ của 200 x 200;

Nó cũng hỗ trợ watermarking.

Check it out tại địa chỉ: http://phpthumb.sourceforge.net/

5

Một lưu ý giá trị bổ sung là để đảm bảo bạn đang mã không tạo ra kích thước "trái phép" của những hình ảnh này.

Vì vậy, URL sau sẽ tạo phiên bản 200x200 của hình ảnh 1234 nếu hình ảnh chưa tồn tại.Tôi muốn cao đề xuất bạn đảm bảo rằng URL được yêu cầu chứa kích thước hình ảnh bạn hỗ trợ.

/images/get/200x200/1234.jpg 

Một người độc hại có thể bắt đầu yêu cầu URL ngẫu nhiên, luôn thay đổi chiều cao & chiều rộng của hình ảnh. Điều này sẽ gây ra máy chủ của bạn một số vấn đề nghiêm trọng b/c nó sẽ được ngồi ở đó, về cơ bản bị tấn công, tạo ra hình ảnh kích thước bạn không hỗ trợ.

/images/get/0x1/1234.jpg 
/images/get/0x2/1234.jpg 
... 
/images/get/0x9999999/1234.jpg 
/images/get/1x1/1234.jpg 
... 
etc 

Dưới đây là một ảnh ngẫu nhiên mã minh họa này:

<?php 

    $pathOnDisk = getImageDiskPath($_SERVER['REQUEST_URI']); 

    if(file_exists($pathOnDisk)) { 
     // send header with image mime type 
     echo file_get_contents($pathOnDisk); 
     exit; 
    } else { 
     $matches = array(); 
     $ok = preg_match(
      '/\/images\/get\/(\d+)x(\d+)\/(\w+)\.jpg/', 
      $_SERVER['REQUEST_URI'], $matches); 

     if(! $ok) { 
      // invalid url 
      handleInvalidRequest(); 
     } else { 
      list(, $width, $height, $guid) = $matches; 

      // you should do this! 
      if(isSupportedSize($width, $height)) { 
       // size is supported. all good 
       // generate the resized image, save it & output it 
      } else { 
       // invalid size requested!!! 
       handleInvalidRequest(); 
      } 
     } 
    } 

    // snip 
    function handleInvalidRequest() { 
     // do something w/ invalid request   
     // show a default graphic, log it etc 
    } 
?> 
+0

Sử dụng die() là mã khủng khiếp. Bạn về cơ bản bảo lãnh, bán phá giá một dòng văn bản cho khách hàng, mà không thực hiện bất kỳ sửa lỗi nào. Nếu ví dụ này được sử dụng trong sản xuất, hãy thay thế các cuộc gọi die() bằng các hình ảnh thay thế hoặc các lỗi hữu ích. –

+0

tôi đồng ý với bạn. chỉ mẫu mã của nó để có được chỉ trên – phatduckk

+0

Điều này đã được thực hiện trong mã của tôi (kích thước hình ảnh tối đa và tối thiểu với một hình ảnh giữ chỗ nếu có điều gì sai). Được thăng hạng vì suy nghĩ về bảo mật PHP luôn tốt! –

30

tôi sẽ làm điều đó một cách khác nhau.

Sự cố: 1. Việc phân phát tệp PHP sẽ kém hiệu quả hơn mức có thể. 2. PHP phải kiểm tra sự tồn tại của các tập tin mỗi khi một hình ảnh được yêu cầu 3. Apache tốt hơn nhiều so với PHP.

Có một vài giải pháp ở đây.

Bạn có thể sử dụng mod_rewrite trên Apache. Có thể sử dụng mod_rewrite để kiểm tra xem tệp có tồn tại không và nếu có, hãy phân phát tệp đó thay thế. Điều này vượt qua PHP hoàn toàn, và làm cho mọi thứ nhanh hơn rất nhiều. Tuy nhiên, cách thực tế để thực hiện điều này là tạo một lược đồ URL cụ thể cần phải luôn tồn tại và sau đó chuyển hướng đến PHP nếu không.

Ví dụ:

RewriteCond %{REQUEST_URI} ^/images/cached/ 
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} !-f 
RewriteRule (.*) /images/generate.php?$1 [L] 

Vì vậy, nếu một khách hàng yêu cầu /images/cached/<something> và tập tin đó không tồn tại, Apache sẽ chuyển hướng yêu cầu đến /images/generate.php?/images/cached/<something>. Kịch bản này sau đó có thể tạo ra hình ảnh, ghi nó vào bộ nhớ cache, và sau đó gửi nó cho khách hàng. Trong tương lai, kịch bản PHP không bao giờ được gọi trừ các hình ảnh mới.

Sử dụng bộ nhớ đệm. Như một người đăng khác đã nói, hãy sử dụng những thứ như mod_expires, Tiêu đề được sửa đổi lần cuối, v.v. để trả lời các yêu cầu GET có điều kiện. Nếu khách hàng không phải yêu cầu lại hình ảnh, tải trang sẽ tăng tốc đáng kể và tải trên máy chủ sẽ giảm.

Đối với trường hợp bạn phải gửi hình ảnh từ PHP, bạn có thể sử dụng mod_xsendfile để làm điều đó với chi phí thấp hơn. Xem the excellent blog post from Arnold Daniels về vấn đề này, nhưng lưu ý rằng ví dụ của anh ấy là để tải xuống. Để cung cấp nội dung hình ảnh, hãy lấy tiêu đề Nội dung-Bố trí (cuộc gọi tiêu đề thứ ba() thứ ba).

Hy vọng điều này sẽ giúp - nhiều hơn sau khi chứng đau nửa đầu của tôi rõ ràng.

+0

Cảm ơn phương pháp tuyệt vời. Kết hợp với các tuyến đường CakePHP, một giải pháp rất thanh lịch. –

+1

Phương pháp tuyệt vời và chính xác những gì tôi cần ngay bây giờ. Tôi ước tôi có thể upvote điều này hai lần. –

+0

Dude - NICE !!! 1 cho thời điểm Heureka –

1

Có vẻ như bài đăng tuyệt vời, nhưng vấn đề của tôi vẫn chưa được giải quyết. Tôi không có quyền truy cập vào htaccess trong nhà cung cấp máy chủ của tôi, do đó, không có câu hỏi về tinh chỉnh apache. Có thực sự là một cách để đặt tiêu đề kiểm soát cace cho hình ảnh?

0

tôi đã quản lý để làm điều này chỉ đơn giản là sử dụng một tiêu đề chuyển hướng trong PHP:

if (!file_exists($filename)) { 

    // *** Insert code that generates image *** 

    // Content type 
    header('Content-type: image/jpeg'); 

    // Output 
    readfile($filename);  

} else { 
    // Redirect 
    $host = $_SERVER['HTTP_HOST']; 
    $uri = rtrim(dirname($_SERVER['PHP_SELF']), '/\\'); 
    $extra = $filename; 
    header("Location: http://$host$uri/$extra"); 
} 
0

Thay vì giữ địa chỉ tập tin trong db Tôi thích thêm một số ngẫu nhiên để tên tập tin bất cứ khi nào người dùng đăng nhập Something như thế này cho người dùng 1234:. Image/picture_1234.png rnd = 6534122341

Nếu? người dùng gửi ảnh mới trong phiên tôi chỉ làm mới số ngẫu nhiên.

GUID khắc phục sự cố bộ nhớ cache 100%. Tuy nhiên nó làm cho nó khó khăn hơn để theo dõi các tập tin hình ảnh. Với phương pháp này, có khả năng người dùng có thể nhìn thấy cùng một hình ảnh một lần nữa khi đăng nhập trong tương lai. Tuy nhiên, tỷ lệ cược thấp nếu bạn tạo số ngẫu nhiên của bạn từ một số tỷ.

Các vấn đề liên quan