2009-08-30 10 views
16

Voglio monitorare la frequenza con cui vengono caricate alcune immagini esterne. Quindi la mia idea è invece di dare un URI direttamente come questo:Serve immagine con script PHP vs caricamento diretto di un'immagine

www.site.com/image1.jpg 

posso creare uno script PHP che legge l'immagine, così ho costruito un file PHP e il mio HTML sarebbe simile a questa:

<img src="www.site.com/serveImage.php?img=image1.jpg"> 

ma non so come leggere l'immagine dal disco e restituirla. Dovrei restituire un array di byte o impostare il tipo di contenuto?

Cordiali saluti, Michel

risposta

9

È necessario impostare il tipo di contenuto:

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

Poi si carica l'immagine e l'uscita in questo modo:

$image=imagecreatefromjpeg($_GET['img']); 
imagejpeg($image); 
+2

imagecreatefromjpeg + imagejpeg potrebbe essere un po 'eccessivo (CPU-consumo) se si desidera solo inviare i dati da un file - il vantaggio che vedo è assicurarsi che si carichi realmente l'immagine; ma probabilmente ci sono altri modi per esserne sicuri (come consentire solo una directory, che contiene solo immagini) –

+15

readfile è meglio se si invierà l'immagine così com'è. – OIS

20

di realizzare qualcosa di simile , lo script dovrà:

  • inviare le intestazioni di destra, che dipendono dal tipo di immagine: image/gif, image/jpeg, image/jpeg, ...
  • inviare i dati dell'immagine
  • assicurandosi niente altro è inviato (senza spazi bianchi, niente di niente)

questo viene fatto con la funzione header, con qualche codice come questo:

header("Content-type: image/gif"); 

Oppure

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

o qualsiasi altra cosa, a seconda del tipo di immagine.


Per inviare i dati dell'immagine, è possibile utilizzare la funzione di readfile:

legge un file e lo scrive nel buffer uscita.

In questo modo, in una funzione, entrambi leggono il file e ne restituiscono il contenuto.


Come sidenote:

  • è necessario mettere un po 'di sicurezza in vigore, al fine di garantire gli utenti non possono richiedere tutto ciò che vogliono tramite script: è necessario assicurarsi che serve solo immagini, dalla directory ti aspetti ; niente come serveImage.php?file=/etc/passwd dovrebbe essere OK, per esempio.
  • Se sei solo disposto a ottenere il numero di volte in cui un file è stato caricato ogni giorno, l'analisi del file di log di Apache potrebbe essere una buona idea (tramite un batch eseguito da cron ogni giorno alle 00:05, che analizza il log di il giorno prima, per esempio); non avrete statistiche in tempo reale, ma richiederà meno risorse sul server (non PHP per servire i file statici)
+1

grazie per il sidenote: • è necessario mettere un po 'di sicurezza sul posto, per garantire che gli utenti non possano richiedere nulla che vogliono tramite il tuo script: devi assicurarti che serva solo immagini, dalla directory che ti aspetti; niente come serveImage.php? file =/etc/passwd dovrebbe essere OK, per esempio. – Michel

3

Sei probabilmente meglio esaminare i log di accesso al server per questo. L'esecuzione di tutte le immagini tramite php potrebbe mettere un po 'di carico sul tuo server.

+0

hmm, questo sicuramente farebbe il trucco. lo salverò quando il carico diventa un problema. – Michel

+0

Inoltre, eseguirli tramite uno script PHP inciderà sul caching lato client, che potrebbe infatti aumentare il carico di lettura. – Rob

+2

@rob: che non ha nulla a che fare con l'esecuzione attraverso uno script, ma dimenticando di inviare le intestazioni giuste. Ho i 2 migliori nella mia risposta. – OIS

33

L'invio di immagini tramite uno script è utile per altre operazioni come il ridimensionamento e il caching su richiesta.

Come risposto da Pascal MARTIN la funzione readfile e queste intestazioni sono i requisiti:

  • Content-Type
    • Il tipo MIME di questo contenuto
    • Esempio: header('Content-Type: image/gif');
    • Vedere la funzione mime_content_type
    • Tipi
      • image/gif
      • image/jpeg
      • image/png

Ma oltre l'ovvio tipo di contenuto che si dovrebbe anche guardare altre intestazioni quali:

  • Content Lunghezza
    • La lunghezza del corpo della risposta in ottetti (byte di 8 bit)
    • Esempio: header('Content-Length: 348');
    • Vedere la funzione filesize
    • Consente connectio essere meglio utilizzate.
  • Last-Modified
    • L'ultima data di modifica per l'oggetto richiesto, nella RFC 2822 formato
    • Esempio: header('Last-Modified: Tue, 15 Nov 1994 12:45:26 GMT');
    • Vedere la funzione filemtime e date formattarlo nella RFC richiesto 2822 formato
      • Esempio: header('Last-Modified: '.date(DATE_RFC2822, filemtime($filename)));
    • È possibile uscire dallo script dopo aver inviato 304 se il tempo di modifica del file è lo stesso.
  • codice di stato
    • Esempio: header("HTTP/1.1 304 Not Modified");
    • si può uscire ora e non inviare l'immagine ancora una volta

Per l'ultima volta modificato, cercare questo in $_SERVER

  • If-Modified-Since
    • Consente un 304 Not Modified da restituire se il contenuto è invariato
    • Esempio: If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT
    • È in $_SERVER con la chiave http_if_modified_since

List of HTTP header responses

+0

Ecco un bel codice che aiuta a implementare tutte le intestazioni di tesi: [collegamento] (http://css-tricks.com/snippets/php/intelligent-php-cache-control/) –

2

Inoltre, se si desidera che l'utente visualizzi un nome file reale in ins tead del vostro scriptname quando l'utente RMC del sull'immagine e seleziona "Salva con nome", dovrai impostare anche questa intestazione:

header('Content-Disposition: filename=$filename'); 
+1

questo può anche essere risolto con reindirizzamento in apache (host virtuale o .htaccess) al file di script. quindi /img/somefile_small.jpg richiama il reindirizzamento interno a showimage.php – OIS

11

a utilizzare la funzione "passante" per chiamare il comando "cat", come this:

header('Content-type: image/jpeg'); 
passthru('cat /path/to/image/file.jpg'); 

Funziona su Linux. Salva risorse.

6

Invece di modificare l'URL dell'immagine diretta nell'HTML, è possibile inserire una riga nella configurazione di Apache o .htaccess per riscrivere tutte le richieste di immagini in una directory su uno script php. Quindi in quello script è possibile utilizzare le intestazioni delle richieste e l'array $_server per elaborare la richiesta e servire il file.

In primo luogo nel vostro .htaccess:

RewriteRule ^(.*)\.jpg$ serve.php [NC] 
RewriteRule ^(.*)\.jpeg$ serve.php [NC] 
RewriteRule ^(.*)\.png$ serve.php [NC] 
RewriteRule ^(.*)\.gif$ serve.php [NC] 
RewriteRule ^(.*)\.bmp$ serve.php [NC] 

Lo script serve.php deve trovarsi nella stessa directory .htaccess. Si dovrà probabilmente scrivere qualcosa del genere: (! Questo script può essere migliorato)

<?php 
$filepath=$_SERVER['REQUEST_URI']; 
$filepath='.'.$filepath; 
if (file_exists($filepath)) 
{ 
touch($filepath,filemtime($filepath),time()); // this will just record the time of access in file inode. you can write your own code to do whatever 
$path_parts=pathinfo($filepath); 
switch(strtolower($path_parts['extension'])) 
{ 
case "gif": 
header("Content-type: image/gif"); 
break; 
case "jpg": 
case "jpeg": 
header("Content-type: image/jpeg"); 
break; 
case "png": 
header("Content-type: image/png"); 
break; 
case "bmp": 
header("Content-type: image/bmp"); 
break; 
} 
header("Accept-Ranges: bytes"); 
header('Content-Length: ' . filesize($filepath)); 
header("Last-Modified: Fri, 03 Mar 2004 06:32:31 GMT"); 
readfile($filepath); 

} 
else 
{ 
header("HTTP/1.0 404 Not Found"); 
header("Content-type: image/jpeg"); 
header('Content-Length: ' . filesize("404_files.jpg")); 
header("Accept-Ranges: bytes"); 
header("Last-Modified: Fri, 03 Mar 2004 06:32:31 GMT"); 
readfile("404_files.jpg"); 
} 
/* 
By Samer Mhana 
www.dorar-aliraq.net 
*/ 
?> 

0

servo le mie immagini con readfile pure, ma io sono andato il miglio supplementare sia per la sicurezza e la funzionalità extra.

Ho un database impostato che memorizza l'ID immagine, le sue dimensioni e l'estensione del file. Ciò significa anche che le immagini devono essere caricate (consentendo il ridimensionamento opzionale), quindi utilizzo il sistema solo per i contenuti e non per le immagini necessarie per il sito stesso (come sfondi o sprite).

Fa anche un ottimo lavoro per essere sicuro di poter richiedere solo immagini.

Così, per servire il flusso di lavoro semplificato sarebbe come questo (non si può inviare il codice di produzione qui):

1) ottenere l'ID dell'immagine richiesto

2) Cercare informazioni nel database

3) intestazioni Gettare in base all'estensione ("jpg" ottiene riassegnati a "jpeg" durante il caricamento)

4) readfile("/images/$id.$extension");

5) Opzionalmente, proteggere/images/dir in modo che non possa essere indicizzato (non è un problema nel mio sistema in quanto mappa URL come /image/view/11 in qualcosa come /index.php?module=image & azione = visualizza & id = 11)

Problemi correlati