PHP: algılama fopen () hataları görüntüleri indirirken

0 Cevap php

Ben oyuncu avatarları gösterilecek olan bir kart oyunu (aşağıda ekran) var.

Avatarlar için ben, ?img= parametre olarak geçirilen bir görüntü URL almak indirmek ve benim CentOS 5 makinede /var/www/cached_avatars/md5_of_that_url altında kurtaracak bir kısa proxy.php komut dosyası, yazdım . Gelecek sefer komut aynı URL ile denir, bu dir bu görüntüyü bulmak ve STDOUT doğrudan hizmet edecektir.

Bu, çoğunlukla iyi çalışır, ancak bazı avatarlar için ilk indirme başarısız (Ben kez dışarı varsayalım) ve oyuncu resmin alt kısmını görmüyorum:

alt text

Ben bir sonraki proxy.php çağrı üzerine tekrar indirilir, böylece bu görüntü indir arızası tespit ve önbelleğe alınan kısmi dosyayı silmek istiyorum.

Ben STREAM_NOTIFY_FAILURE Akımda ya da benim geri arama STREAM_NOTIFY_COMPLETED olayları tespit denedim, ama onlar ateş değildir. Gördüğüm sadece olayları: STREAM_NOTIFY_CONNECT, STREAM_NOTIFY_MIME_TYPE_IS, STREAM_NOTIFY_FILE_SIZE_IS, STREAM_NOTIFY_REDIRECTED, STREAM_NOTIFY_PROGRESS:

Nov  3 18:48:27 httpd: 2  0
Nov  3 18:48:27 httpd: 4 image/jpeg 0
Nov  3 18:48:27 httpd: 5 Content-Length: 45842 0
Nov  3 18:48:27 httpd: 7  0
Nov  3 18:48:27 last message repeated 16 times
Nov  3 18:48:39 httpd: 2  0
Nov  3 18:48:40 httpd: 4 image/jpeg 0
Nov  3 18:48:40 httpd: 5 Content-Length: 124537 0
Nov  3 18:48:40 httpd: 7  0

Ve benim bile büyük sorun ben geri arama içine önbelleğe $ img veya $ gibi değişkenleri geçemez ya da ben bir STREAM_NOTIFY_FILE_SIZE_IS olay geri arama bir $ uzunluk değişken ayarlayın ve sonra ($ önbellekli) dosya boyutu ile karşılaştırın yani, ana komut (I uyuşmazlığını algılayamaz ve dosyayı silebilir):

Nov  3 18:50:17 httpd: PHP Notice:  Undefined variable: length in /var/www/html/proxy.php on line 58
Nov  3 18:50:17 httpd: length=

Herkes benim problem için bir çözüm var mı?

Ben PHP kıvırmak kütüphanede baktım, ama nasıl bana burada yardımcı olabilir görmüyorum.

Aşağıda benim senaryom, ben kısalık için URL sağlık kontrolleri ihmal ettik:

<?php

define('MAX_SIZE', 1024 * 1024);
define('CACHE_DIR', '/var/www/cached_avatars/');

$img = urldecode($_GET['img']);

$opts = array(
        'http' => array(
                'method' => 'GET'
        )
);

$cached = CACHE_DIR . md5($img);

$finfo = finfo_open(FILEINFO_MIME);
$readfh = @fopen($cached, 'rb');
if ($readfh) {
        header('Content-Type: ' . finfo_file($finfo, $cached));
        header('Content-Length: ' . filesize($cached));

        while (!feof($readfh)) {
                $buf = fread($readfh, 8192);
                echo $buf;
        }

        fclose($readfh);
        finfo_close($finfo);
        exit();
}

$ctx = stream_context_create($opts);
stream_context_set_params($ctx, array('notification' => 'callback'));
$writefh = fopen($cached, 'xb');
$webfh = fopen($img, 'r', FALSE, $ctx);
if ($webfh) {
        $completed = TRUE;

        while (!feof($webfh)) {
                $buf = fread($webfh, 8192);
                echo $buf;
                if ($writefh)
                        fwrite($writefh, $buf);
        }

        fclose($webfh);
        if ($writefh)
                fclose($writefh);

        # XXX can't access $length in callback
        error_log('length=' . $length);

        # XXX can't access $completed in callback
        if (!$completed)
                unlink($cached);
}

function callback($code, $severity, $message, $message_code, $bytes_transferred, $bytes_total) {
        error_log(join(' ', array($code, $message, $message_code)));

        if ($code == STREAM_NOTIFY_PROGRESS && $bytes_transferred > MAX_SIZE) {
                exit('File is too big: ' . $bytes_transferred);

        } else if ($code == STREAM_NOTIFY_FILE_SIZE_IS) {
                if ($bytes_total > MAX_SIZE)
                        exit('File is too big: ' . $bytes_total);
                else {
                        header('Content-Length: ' . $bytes_total);
                        # XXX can't pass to main script
                        $length = $bytes_total;
                }

        } else if ($code == STREAM_NOTIFY_MIME_TYPE_IS) {
                if (stripos($message, 'image/gif') !== FALSE ||
                    stripos($message, 'image/png') !== FALSE ||
                    stripos($message, 'image/jpg') !== FALSE ||
                    stripos($message, 'image/jpeg') !== FALSE) {
                        header('Content-Type: ' . $message);
                } else {
                        exit('File is not image: ' . $mime);
                }
        } else if ($code == STREAM_NOTIFY_FAILURE) {
                $completed = FALSE;
        }
}

?>

Benim komut herhangi bir dosya kilitleme kullanmayın: (hala indirilen ediliyor çünkü) bir süre sonra eksik dosya dönmek için önbellek bir okuma için ok. Ama hiçbir kısmen indirilmiş görüntüleri ücretsiz Önbelleğimi tutmak istiyorum. Benim yazıya bakarsanız Ayrıca ben 1 dosyaya yazı birkaç komut önlemek gerektiğini "xb" kullanın, bu yüzden aynı anda yazı burada bir sorun değildir.

0 Cevap