2010-11-04 20 views
0

Je suis en train d'écrire un script, qui cache des images, mais je suis bloqué avec le message d'erreur suivant:boucle PHP: curl_setopt() fopencookie échoué

Nov 4 12:55:19 centos httpd: PHP Fatal error: curl_setopt() [<a href='function.curl-setopt'>function.curl-setopt</a>]: fopencookie failed in /var/www/html/proxy3.php on line 6 

J'ai préparé un script simple qui a toujours ce problème:

<?php 
#phpinfo(); 
$fh = fopen('/tmp/yahoo.html', 'xb'); 
if ($fh) { 
     $ch = curl_init('http://www.yahoo.com/'); 
     curl_setopt($ch, CURLOPT_FILE, $fh); # XXX the line 6 
     curl_setopt($ch, CURLOPT_HEADER, FALSE); 
     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); 
     curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 
     #curl_setopt($ch, CURLOPT_COOKIEJAR, '/dev/null'); 
     #curl_setopt($ch, CURLOPT_COOKIEFILE, '/dev/null'); 
     #curl_setopt($ch, CURLOPT_COOKIEJAR, '/tmp/cookies.txt'); 
     #curl_setopt($ch, CURLOPT_COOKIEFILE, '/tmp/cookies.txt'); 
     curl_exec($ch); 

     if(!curl_errno($ch)) { 
       $info = curl_getinfo($ch); 
        echo 'Took '.$info['total_time'] . 
        's to send a request to '.$info['url']; 
     } 
     curl_close($ch); 
     fclose($fh); 
} else { 
     echo 'Can not open /tmp/yahoo.html'; 
} 
?> 

Dans le répertoire/tmp Je vois alors un fichier de taille zéro:

[email protected]:html> ls -alZ /tmp/yahoo.html 
-rw-r--r-- apache apache user_u:object_r:httpd_tmp_t  /tmp/yahoo.html 

fait un Y a-t-il une idée, qu'est-ce qui ne va pas ici?

J'ai essayé d'installer/ne pas fixer CURLOPT_COOKIEJAR et CURLOPT_COOKIEFILE -/dev/null et/ou /tmp/cookies.txt. J'ai essayé sudo touch /tmp/cookies.txt; sudo chown apache.apache /tmp/cookies.txt aussi. Cela ne fonctionne tout simplement pas.

En fait, je n'ai pas besoin de cookies dans mon script, je serais heureux de les désactiver dans curl. Exprès fopen (..., "xb") exprès, de sorte que seulement 1 instance de manuscrit écrira au dossier mis en cache dans mon vrai manuscrit.

J'utilise CentOS 5.5 avec php-5.1.6-27.el5 et php.ini non modifiée

Merci, Alex

post-scriptum Et voici mon vrai script de proxy d'image, qui échoue avec le même message d'erreur fopencookie. Je ne peux pas utiliser fopen (...., 'wb') là, je doit utiliser fopen (.... 'XB'):

<?php 

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

$img = urldecode($_GET['img']); 
# URL sanity checks omitted here for brevity 
$cached = CACHE_DIR . md5($img); 
$writefh = @fopen($cached, 'xb'); 
# the file is not cached yet, download it! 
if ($writefh) { 
     $ch = curl_init($img); 
     curl_setopt($ch, CURLOPT_FILE, $writefh); 
     curl_setopt($ch, CURLOPT_HEADER, FALSE); 
     #curl_setopt($ch, CURLOPT_REFERER, $matches[1]); 
     curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 
     curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); 
     #curl_setopt($ch, CURLOPT_COOKIEJAR, '/dev/null'); 
     #curl_setopt($ch, CURLOPT_COOKIEFILE, '/dev/null'); 
     #curl_setopt($ch, CURLOPT_COOKIEJAR, CACHE_DIR . 'cookies.txt'); 
     #curl_setopt($ch, CURLOPT_COOKIEFILE, CACHE_DIR . 'cookies.txt'); 
     curl_exec($ch); 

     $error = curl_errno($ch); 
     $length = curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD); 
     $mime  = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); 
     $is_image = ($mime != NULL && 
        (stripos($mime, 'image/gif') !== FALSE || 
         stripos($mime, 'image/png') !== FALSE || 
         stripos($mime, 'image/jpg') !== FALSE || 
         stripos($mime, 'image/jpeg') !== FALSE)); 

     curl_close($ch); 
     fclose($writefh); 

     if ($error || $length < MIN_SIZE || $length > MAX_SIZE || !$is_image) { 
       unlink($cached); 
       exit('Download failed: ' . $img); 
     } 
} else { 
     $finfo = finfo_open(FILEINFO_MIME); 
     $mime = finfo_file($finfo, $cached); 
     $length = filesize($cached); 
     finfo_close($finfo); 
} 

$readfh = fopen($cached, 'rb'); 
if ($readfh) { 
     header('Content-Type: ' . $mime); 
     header('Content-Length: ' . $length); 

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

     fclose($readfh); 

} 

?> 

Répondre

0

Merci pour toutes les réponses, je l'ai fini avec ce PHP/cURL-script pour la mise en cache des images (nécessaire par les applications flash pour contourner une crossdomain.xml manquante) - semble fonctionner ok avec CentOS 5 Linux et php-5.1.6-27.el5:

<?php 

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

$img = urldecode($_GET['img']); 
# img sanity checks omitted here 
$cached = CACHE_DIR . md5($img); 

if (is_readable($cached)) { 
     $finfo = finfo_open(FILEINFO_MIME); 
     $mime = finfo_file($finfo, $cached); 
     $length = filesize($cached); 
     finfo_close($finfo); 
} else { 
     $writefh = fopen($cached, 'wb'); 
     if ($writefh) { 
       flock($writefh, LOCK_EX); 
       $ch = curl_init($img); 
       curl_setopt($ch, CURLOPT_FILE, $writefh); 
       curl_setopt($ch, CURLOPT_HEADER, FALSE); 
       curl_setopt($ch, CURLOPT_REFERER, $matches[1]); 
       curl_setopt($ch, CURLOPT_USERAGENT, $_SERVER['HTTP_USER_AGENT']); 
       curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE); 
       curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE); 
       curl_exec($ch); 

       $error = curl_errno($ch); 
       $length = curl_getinfo($ch, CURLINFO_SIZE_DOWNLOAD); 
       $mime  = curl_getinfo($ch, CURLINFO_CONTENT_TYPE); 
       $is_image = ($mime != NULL && 
          (stripos($mime, 'image/gif') !== FALSE || 
           stripos($mime, 'image/png') !== FALSE || 
           stripos($mime, 'image/jpg') !== FALSE || 
           stripos($mime, 'image/jpeg') !== FALSE)); 

       curl_close($ch); 
       fclose($writefh); 
       if ($error || $length < MIN_SIZE || $length > MAX_SIZE || !$is_image) { 
         unlink($cached); 
         exit('Download failed: ' . $img); 
       } 
     } 
} 

$readfh = fopen($cached, 'rb'); 
if ($readfh) { 
     header('Content-Type: ' . $mime); 
     header('Content-Length: ' . $length); 

     flock($readfh, LOCK_SH); 

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

     fclose($readfh); 
} 

?> 
0

Je pense que le problème est à cause du mode x. fopen lorsqu'il est utilisé avec le mode x renvoie false si le fichier existe déjà. Dans votre cas, le fichier existe déjà, $fh sera false et lorsque cela est passé à curl_setopt, vous obtenez cette erreur.

Pour résoudre ce problème, remplacez xb par wb.

+0

Non, au 1ère exécution le fichier /tmp/yahoo.html n'existe pas. J'ai réécrit mon code pour le rendre plus clair. Il échoue toujours avec le message d'erreur (trompeur?) Fopencookie. –

0

Si ce que vous voulez est qu'un seul script pour accéder au fichier en même temps, vous devez utiliser l'option + cbflock:

$fh = fopen('/tmp/yahoo.html', 'cb'); 
if (flock($fh, LOCK_EX | LOCK_NB) { 
    //ftruncate($fh, 0); -- truncate the file if that's what you want 
    //continue as usual 
} 
else { 
    //could not obtain lock (without waiting) 
} 
+0

fopen (...., "xb") est une meilleure option pour moi, parce que je veux télécharger l'image une seule fois (s'il vous plaît voir le vrai script au bas de ma question). Avec "cb" il sera téléchargé encore et encore.Aussi, je pense que flock() n'est pas nécessaire, quand vous utilisez "cb". Mais de toute façon, merci pour votre réponse. J'ai aussi déposé un bug PHP sur http://bugs.php.net/bug.php?id=53241 –

+1

@Alex J'ai corrigé le bug, il sera en PHP 5.3.4, ce qui est dû à Décembre . Je n'ai pas testé, mais je pense que 'cb' aura le même problème que 'xb', c'est-à-dire qu'un fichier ouvert avec 'cb' donnera aussi une erreur fopencookie. Je ne peux vraiment pas voir une solution de rechange ici, sauf en utilisant un fichier séparé avec 'xb' comme un verrou et les si fopen est un succès, ouvrez le vrai avec avec 'wb'. – Artefacto

+0

Merci, je vais m'en tenir à utiliser fopen (..., 'wb') et flock() si longtemps. –