Asked  7 Months ago    Answers:  5   Viewed   33 times

I'm displaying images from outside my web root, like this:

header('Content-type:image/png');
readfile($fullpath);

The content-type: image/png is what confuses me.

Someone else helped me out with this code, but I noticed that not all images are PNG. Many are jpg or gif.
And still they are displayed successfully.

does anyone know why?

 Answers

52

The best solution would be to read in the file, then decide which kind of image it is and send out the appropriate header

$filename = basename($file);
$file_extension = strtolower(substr(strrchr($filename,"."),1));

switch( $file_extension ) {
    case "gif": $ctype="image/gif"; break;
    case "png": $ctype="image/png"; break;
    case "jpeg":
    case "jpg": $ctype="image/jpeg"; break;
    case "svg": $ctype="image/svg+xml"; break;
    default:
}

header('Content-type: ' . $ctype);

(Note: the correct content-type for JPG files is image/jpeg)

Wednesday, March 31, 2021
 
insomiac
answered 7 Months ago
36

Checking the engine source for headers_list and http_response_code, notice that the value for general headers and status code are separated:

// headers_list
SG(sapi_headers).headers

// http_response_code
SG(sapi_headers).http_response_code

But HTTP response code isn't the only header with dedicated storage: Content-Type does, too:

SG(sapi_headers).mimetype = NULL;

So what's going on here? The complete header() algorithm specifically checks for the following strings to adjust state:

  • HTTP/
  • Content-Type
  • Content-Length
  • Location
  • WWW-Authenticate

HTTP/ is checked specifically because that's how one set the status code explicitly before PHP 5.4: after that, http_response_code is available and is recommended for clarity. That header() was used is confusing, for the reason you're asking in this question and on general principle: the http header BNF clearly doesn't include status line:

header-field   = field-name ":" OWS field-value OWS

PHP handles the others separately because they are single-value headers and/or their value matters for efficiency in later calculations.

TL;DR: HTTP/ set by header() isn't included in headers_list() because HTTP/ status lines are not headers in the strict RFC sense. But for the PHP < 5.4 limitation that header() was the only way to set HTTP/ status, it'd likely have never been a confusing issue.

Wednesday, March 31, 2021
 
hillz
answered 7 Months ago
80

I would use this one:

header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);

$_SERVER['SERVER_PROTOCOL'] contains the protocol used in the request like HTTP/1.0 or HTTP/1.1.


Edit    I have to admit that my suggestion is senseless. After a few tests I noticed that if the first parameter is a valid HTTP status line, PHP will use that status line regardless if and what second status code was given with the third parameter. And the second parameter (documentation names it replace) is useless too as there can not be multiple status lines.

So the second and third parameter in this call are just redundant:

header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified', true, 304);

Use just this instead:

header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified');
Saturday, May 29, 2021
 
Juicy
answered 5 Months ago
100

Sorry, I'm not sure what is you want.

This is the example to get from a image url, echo header and save image to a file.

But, if you want a proxy, you should use web server (Nginx, Apache, etc), PHP is no need

<?php
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, "http://img3.cache.netease.com/www/logo/logo_png.png");
curl_setopt($ch, CURLOPT_HEADER, 1);
curl_setopt($ch, CURLOPT_REFERER, "http://www.163.com/");
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_BINARYTRANSFER, 1);
$return = curl_exec($ch);
curl_close($ch);

list($header, $image) = explode("rnrn", $return, 2);

echo $header;

file_put_contents("/tmp/logo.png", $image);
Saturday, May 29, 2021
 
jab
answered 5 Months ago
jab
59

Try this code,work fine on my machine.

<?php

$image = 'http://www.google.com/doodle4google/images/d4g_logo_global.jpg';
$imageData = base64_encode(file_get_contents($image));
echo '<img src="data:image/jpeg;base64,'.$imageData.'">';
?>
Sunday, October 3, 2021
 
Connor Johnson
answered 3 Weeks ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :