2012-12-19 40 views
11

Tôi biết rằng có ít nhất 10 câu hỏi giống nhau với câu trả lời nhưng không ai trong số họ có vẻ làm việc cho tôi một cách hoàn hảo. Tôi đang cố gắng kiểm tra xem hình ảnh bên trong hay bên ngoài có tồn tại (URL hình ảnh có hợp lệ không?).Cách PHP đúng để kiểm tra xem hình ảnh bên ngoài có tồn tại không?

  1. fopen($url, 'r') thất bại trừ khi tôi sử dụng @fopen():

    Warning: fopen(http://example.com/img.jpg) [function.fopen]: failed to open stream: HTTP request failed! HTTP/1.1 404 Not Found in file.php on line 21 
    
  2. getimagesize($img) không thành công khi hình ảnh không tồn tại (PHP 5.3.8):

    Warning: getimagesize() [function.getimagesize]: php_network_getaddresses: getaddrinfo failed 
    
  3. CURL thất bại vì nó isn' t được hỗ trợ bởi một số máy chủ (mặc dù nó hiện diện chủ yếu ở khắp mọi nơi).
  4. fileExists() không thành công do không hoạt động với URL bên ngoài và không thể kiểm tra xem chúng tôi có đang xử lý hình ảnh hay không.

Bốn phương pháp là câu trả lời phổ biến nhất cho câu hỏi đó là sai. Điều gì sẽ là cách chính xác để làm điều đó?

+4

cURL là câu trả lời đúng. Nếu nó không được máy chủ của bạn hỗ trợ, hãy cấu hình nó. – Brad

+1

@Bard Tôi đang phát triển các chủ đề WP - Tôi không thể yêu cầu mọi người cấu hình điều đó. Nó phải làm việc ra khỏi hộp cho tất cả mọi người. – Atadj

+0

Tất cả các phương pháp khác của bạn sẽ thất bại nếu url fopen bị tắt, do đó bạn không đạt được bất kỳ thứ gì. –

Trả lời

14

getimagesize($img) fails when image doesn't exist: không chắc chắn bạn hiểu những gì bạn muốn .....

TỪ PHP DOC

Các getimagesize() chức năng sẽ xác định kích thước của bất kỳ tập tin hình ảnh nhất định và trở lại kích thước cùng với loại tệp và chuỗi văn bản chiều cao/chiều rộng được sử dụng bên trong thẻ HTML IMG bình thường và loại nội dung HTTP tương ứng.

Khi lỗi, FALSE được trả lại.

Ví dụ

$img = array("http://i.stack.imgur.com/52Ha1.png","http://example.com/img.jpg"); 
foreach ($img as $v) { 
    echo $v, getimagesize($v) ? " = OK \n" : " = Not valid \n"; 
} 

Output

http://i.stack.imgur.com/52Ha1.png = OK 
http://example.com/img.jpg = Not valid 

getimagesize công trình tốt

Sửa

@ Paul .Nhưng câu hỏi của bạn về cơ bản được nói "Làm thế nào để xử lý việc này vì vậy tôi sẽ không nhận được một lỗi khi có một điều kiện lỗi". Và câu trả lời cho điều đó là "bạn không thể". Bởi vì tất cả các chức năng này sẽ kích hoạt một lỗi khi có một điều kiện lỗi. Vì vậy, (nếu bạn không muốn lỗi), bạn sẽ chặn nó. Không có vấn đề nào trong số này sẽ quan trọng trong sản xuất vì bạn không nên hiển thị lỗi anyway ;-) - DaveRandom

+0

Trong trường hợp của tôi trên PHP 5.3, nó trả về Cảnh báo PHP đã đề cập ở trên. Bạn có thể xem nó không? Nó sẽ là tuyệt vời nếu nó trở về sai. Tôi đang ở trên chia sẻ lưu trữ trung bình (nhưng tốt với một số chức năng được kích hoạt). – Atadj

+0

Vấn đề là 'getimagesize()' chỉ sử dụng trình bao bọc fopen HTTP, đây là nơi cảnh báo của bạn đang diễn ra. – Brad

+0

@Bard Có cách nào để biến điều đó thành thứ gì đó không trả về Cảnh báo PHP không? Nó chỉ là lạ - đó là lần đầu tiên tôi nhìn thấy và sử dụng chức năng này và nó không có vẻ làm việc trên chia sẻ lưu trữ. – Atadj

0

Bạn có thể sử dụng Gói PEAR/HTTP_Request2 cho việc này. Bạn có thể tìm thấy nó here

Đây là một ví dụ. Ví dụ này hy vọng rằng bạn đã cài đặt hoặc tải xuống gói HTTP_Request2 đúng cách. Nó sử dụng bộ chuyển đổi ổ cắm kiểu cũ, không bị cong.

<?php 

require_once 'HTTP/Request2.php'; 
require_once 'HTTP/Request2/Adapter/Socket.php'; 

$request = new HTTP_Request2 (
    $your_url, 
    HTTP_Request2::METHOD_GET, 
    array('adapter' => new HTTP_Request2_Adapter_Socket()) 
); 

switch($request->send()->getResponseCode()) { 

    case 404 : 
     echo 'not found'; 
     break; 

    case 200 : 
     echo 'found'; 
     break; 

    default : 
     echo 'needs further attention'; 

} 
+0

Nếu anh ta gặp vấn đề với việc có cURL trên tay, điều này chắc chắn sẽ thất bại trừ khi đi kèm với chủ đề. – Brad

+0

Nó cũng hỗ trợ bộ điều hợp ổ cắm kiểu cũ. điều này hoạt động mà không có curl. chuẩn bị một ví dụ – hek2mgl

0

Sử dụng fsockopen, kết nối với máy chủ, gửi một yêu cầu HEAD và xem những gì tình trạng bạn trở lại.

Thời gian duy nhất bạn cần biết về các sự cố là nếu miền không tồn tại.

Ví dụ mã:

$file = "http://example.com/img.jpg"; 
$path = parse_url($file); 
$fp = @fsockopen($path['host'],$path['port']?:80); 
if(!$fp) echo "Failed to connect... Either server is down or host doesn't exist."; 
else { 
    fputs($fp,"HEAD ".$file." HTTP/1.0\r\n" 
    ."Host: ".$path['host']."\r\n\r\n"); 
    $firstline = fgets($fp); 
    list(,$status,$statustext) = explode(" ",$firstline,3); 
    if($status == 200) echo "OK!"; 
    else "Status ".$status." ".$statustext."..."; 
} 
+0

Vẫn còn rất nhiều máy chủ không hỗ trợ yêu cầu HEAD. Thật không may, một GET là vẫn còn cần thiết, trừ khi bạn muốn thử HEAD đầu tiên và rơi trở lại GET. – Brad

-1

Có nhiều bước, không có giải pháp duy nhất:

  1. Validate URL
  2. Kiểm tra xem các tập tin có sẵn (có thể được thực hiện trực tiếp với bước 3)
  3. Tải hình ảnh xuống tệp tmp.
  4. Sử dụng getimagesize để kiểm tra kích thước của hình ảnh.

Đối với loại công việc này, bạn có thể nắm bắt các ngoại lệ và xử lý chúng tốt để xác định câu trả lời của bạn. Trong trường hợp này, bạn thậm chí có thể ngăn chặn các lỗi vì nó dự định rằng họ lừa có thể thất bại. Vì vậy, bạn xử lý các lỗi chính xác.

Vì không thể thực hiện kiểm tra 100% trên trang mà không cần tải xuống hình ảnh thực tế. Vì vậy, bước 1 và 2 là bắt buộc, 3 và 4 tùy chọn cho câu trả lời dứt khoát hơn.

1

Nếu bạn đang sử dụng PHP> = 5.0.0, bạn có thể chuyển thông số bổ sung vào fopen để chỉ định tùy chọn ngữ cảnh cho HTTP, trong số đó có bỏ qua mã trạng thái không.

$contextOptions = array('http' => array('ignore_errors' => true)); 

$context = stream_context_create($contextOptions); 

$handle = fopen($url, 'r', false, $context); 
+0

Có vẻ như một câu trả lời hay! Và có thể được sử dụng kết hợp với 'getimagesize ($ img)'. – Atadj

13

Mã này thực sự là kiểm tra tệp ... Nhưng nó hoạt động cho hình ảnh!

$url = "http://www.myfico.com/Images/sample_overlay.gif"; 
$header_response = get_headers($url, 1); 
if (strpos($header_response[0], "404") !== false) 
{ 
    // FILE DOES NOT EXIST 
} 
else 
{ 
    // FILE EXISTS!! 
} 
+0

nếu bạn thực sự muốn nó kiểm tra hình ảnh của chúng tôi như: $ header_response ['Content-Type'] ==" image/jpeg " –

+0

Và nếu hình ảnh bị hỏng thì sao? –

4
function checkExternalFile($url) 
{ 
    $ch = curl_init($url); 
    curl_setopt($ch, CURLOPT_NOBODY, true); 
    curl_exec($ch); 
    $retCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); 
    curl_close($ch); 

    return $retCode; 
} 

$fileExists = checkExternalFile("http://example.com/your/url/here.jpg"); 

// $fileExists > 400 = not found 
// $fileExists = 200 = found. 
0

tôi thấy cố gắng nắm bắt những giải pháp tốt nhất cho việc này. Nó làm việc tốt với tôi.

try{ 
     list($width, $height) = getimagesize($h_image->image_url); 
    } 
catch (Exception $e) 
    { 
    } 
0

Tôi biết bạn đã viết "không có curl" nhưng vẫn còn, ai đó có thể tìm thấy hữu ích này:

function curl_head($url) { 

    $ch = curl_init($url); 

    //curl_setopt($ch, CURLOPT_USERAGENT, 'Your user agent'); 
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); 
    curl_setopt($ch, CURLOPT_HEADER, 1); # get headers 
    curl_setopt($ch, CURLOPT_NOBODY, 1); # omit body 
    //curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 1); # do SSL check 
    //curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 2); # verify domain within cert 
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); # follow "Location" redirs 
    //curl_setopt($ch, CURLOPT_TIMEOUT_MS, 700); # dies after 700ms 

    $result = curl_exec($ch); 

    curl_close($ch); 

    return $result; 
} 

print_r(curl_head('https://www.example.com/image.jpg')); 

Bạn sẽ thấy someting như HTTP/1.1 200 OK này hoặc HTTP/1.1 404 Not Found trong mảng tiêu đề trở lại. Bạn cũng có thể thực hiện nhiều yêu cầu song song với curl multi.

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