Transferring and displaying image from remote location - php

I need to read an image (based on HTTP) on an SSL connection. This script reads the image location and encodes/decodes it, then transfers the file contents and returns the image. However, I keep getting the error cannot be displayed because it contains errors.
Here is my code:
<?php
$image = 'http://www.teleovronnaz.ch/webcam/ovronnazweb.jpg';
$info = getimagesize($image);
$strFileExt = image_type_to_extension($info[2]);
if($strFileExt == '.jpg' or $strFileExt == '.jpeg'){
header('Content-Type: image/jpeg');
}elseif($strFileExt == '.png'){
header('Content-Type: image/png');
}elseif($strFileExt == '.gif'){
header('Content-Type: image/gif');
}else{
die('not supported');
}
if($strFile != ''){
$cache_ends = 60*60*24*365;
header("Pragma: public");
header("Cache-Control: maxage=". $cache_ends);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cache_ends).' GMT');
$img_safe = file_get_contents($strFile);
echo $img_safe;
}
exit;
?>

This worked for me.
<?php
$url = 'http://www.teleovronnaz.ch/webcam/ovronnazweb.jpg';
header('Content-type: image/jpeg');
readfile($url);
?>

I don't know why you do it so complicated. I just stripped your cache handling, but really
<?PHP
$image = 'http://www.teleovronnaz.ch/webcam/ovronnazweb.jpg';
$imageContent = file_get_contents($image);
header("Content-Type: image/jpeg");
echo $imageContent;
die(1);
?>
Is enough to display the image. No base64 or additional stuff needed. And if the url is static, you don't even need the distinction of the file extension. You stated an image - that's singular. So I'm guessing that's the only use case here.
I just took some more time to explain a few things:
read an image (based on HTTP) on an SSL connection
If it's HTTP, there is no SSL. That's what HTTPS is for.
This script reads the image location and encodes/decodes it,
I don't know what you think, but it is not. It is base64_encoding the URL to directly decode it again into another variable. That's like doing the following: 0 is your $image - then you make $image+1 (base64_encode) - which will result in 1 - then you do $image-1 (base64_decode) which will result in 0 again.

Related

How to return image from php file set as img src

I am setting up a random image function but trying to prove the concept before handling the randomizer.
Right now I have a test.php file. It contains:
<?php
$img = 'http://example.com/img.jpg';
$fp = fopen($img, 'rb');
header('Content-type: image/jpeg;');
header("Content-Length: " . filesize($img));
fpassthru($fp);
exit;
?>
And then in another html file I have <img src="test.php">
The goal is just to return the image. The image url works is right, and test.php returns a 200. But the image just shows the little broken image icon.
I have also tried readfile() with no luck.
I am just trying to show this image.
filesize does not work on HTTP URLs. The docs say:
This function can also be used with some URL wrappers. Refer to Supported Protocols and Wrappers to determine which wrappers support stat() family of functionality.
However, the HTTP wrapper does not support the stat function. Because of this, you send a wrong Content-Length header and the HTTP response cannot be interpreted by your browser.
I see two possible solutions:
Load the image into memory and use strlen:
$image = file_get_contents('http://example.com/img.jpg');
header('Content-type: image/jpeg;');
header("Content-Length: " . strlen($image));
echo $image;
Use the $http_response_header variable to read the remote response's Content-Length header:
$img = 'http://example.com/img.jpg';
$fp = fopen($img, 'rb');
header('Content-type: image/jpeg;');
foreach ($http_response_header as $h) {
if (strpos($h, 'Content-Length:') === 0) {
header($h);
break;
}
}
fpassthru($fp);
Another alternative would be to use some of the various built in functions for generating / manipulating images - in the case of the code below it is for a png but similar functions exist for jpg,gif and bmp.
Using a url as the filepath relies upon that setting being enabled by your host ( on dev obviously you control whether it is enabled or not )
Using these functions also gives you the possibility to add your own text at runtime, combine images and all sorts of other cool things.
<?php
if( ini_get( 'allow_url_fopen' ) ){
$imgPath='http://localhost/images/filename.png';
} else {
$imgPath=realpath( $_SERVER['DOCUMENT_ROOT'].'/images/filename.png' );
}
header("Content-type: image/png");
$image = imagecreatefrompng($imgPath);
imagesavealpha($image,true);
imagealphablending($image,true);
imagepng($image);
imagedestroy($image);
?>

trouble of show http image in https

I need to embed http image in my https website, because if simply use <img src="http://www.sof.com/abc.jpg"/> will not show in https website.
After that, I was search some topic of this function, I found that something like <img src="https://www.some.com/image.php?url=http://www.sof.com/abc.jpg" /> can be show in https
So now I was genarate 2 source. 1 is the image file: http://www.website1.com/abc.png,
and the https web adress is https://fb.ccc.com
after that I create the image.php code was below:
<?
$strFile = base64_decode(#$_GET['url']);
$strFileExt = end(explode('.' , $strFile));
if($strFileExt == 'jpg' or $strFileExt == 'jpeg'){
header('Content-Type: image/jpeg');
}elseif($strFileExt == 'png'){
header('Content-Type: image/png');
}elseif($strFileExt == 'gif'){
header('Content-Type: image/gif');
}else{
die('not supported');
}
if($strFile != ''){
$cache_expire = 60*60*24*365;
header("Pragma: public");
header("Cache-Control: maxage=". $cache_expire);
header('Expires: ' . gmdate('D, d M Y H:i:s', time() + $cache_expire).' GMT');
}
exit;
?>
if I request the link: https://fb.ccc.com/image.php?url=http://www.website1.com/abc.png , then the page will be respone not supported
I was also try $strFile = $_GET['url']; but it only show blank.
if I try $strFile = var_dump(#$_GET['url']); and the page will respone string(31) "http://www.website1.com/abc.png" not supported
so someone can help to find out what is my script problem?
thank you very much!

Large images load slowly when sending via php vs straight links

When we output images via PHP with image_jpeg or file_get_contents it takes more than twice as long as when we use straight links to the jpg files.
These files are about 180kb.
With our thumbnails (4kb images) there's not much of a time difference between the link and output via PHP.
Anyone know of a why PHP output is slower with larger files and a way to fix it?
All I can think of is that it is being parsed twice when parsed through PHP, instead of directly sending it to the client. Because file_get_contents does what it says, it reads the contents, then sends it to the client. I could be wrong though.
There is different between image_jpeg and file_get_contents. The first is a gd function that creates a jpeg and this take time. The second just reads data from a file.
The problem is how you output it to the browser. If you don't take appropriate measures, content is never cached, so the browser has to download it every time. Static images are always cached by the browser and after the first load, takes almost no time (just a HEAD request).
Try this code:
function CachedFileResponse($thefile,$nocache=0) {
if (!file_exists($thefile)) {
error_log('cache error: file not found: '.$thefile);
header('HTTP/1.0 404 Not Found',true,404);
} else {
$lastmodified=gmdate('D, d M Y H:i:s \G\M\T', filemtime($thefile));
$etag = '"'.md5($lastmodified.filesize($thefile).$thefile).'"';
header('ETag: '.$etag);
header('Last-Modified: '.$lastmodified);
header('Cache-Control: max-age=3600');
header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time()+86400));
$ext=strtolower(substr($thefile,strrpos($thefile,'.')+1));
$fname=substr($thefile,strrpos($thefile,'/')+1);
if ($ext=='jpg' || $ext=='jpeg') {
header('Content-Type: image/jpeg');
} elseif ($ext=='gif') {
header('Content-Type: image/gif');
} elseif ($ext=='png') {
header('Content-Type: image/png');
} else {
header('Content-Type: application/binary');
}
header('Content-Length: ' . filesize($thefile));
header('Content-Disposition: filename="'.$fname.'"');
$ifmodifiedsince = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ? stripslashes($_SERVER['HTTP_IF_MODIFIED_SINCE']) : false;
$ifnonematch = isset($_SERVER['HTTP_IF_NONE_MATCH']) ? stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) : false;
if ($nocache || (!$ifmodifiedsince && !$ifnonematch) ||
($ifnonematch && $ifnonematch != $etag) ||
($ifmodifiedsince && $ifmodifiedsince != $lastmodified)) {
error_log('cache miss: '.$thefile);
$fp = fopen($thefile, 'rb');
fpassthru($fp);
fclose($fp);
} else {
error_log('cache hit: '.$thefile);
header("HTTP/1.0 304 Not Modified",true,304);
}
}
}

PHP output image issues

if (file_exists($path)) {
$fileContent = id3_getImage($path);
$fileMime = id3_getMimeOfImage($path); // is set to image/jpeg
if ($fileMime != "") {
header('Content-Type: '.$fileMime);
print($fileContent);
die;
}
}
So the above code does not work in the browser, however when I make a image with image
$img = imagecreatefromstring($fileContent);
imagejpeg($img, 'test.jpg');die;
the image is created and I can view it on my computer. So I have no clue what I am doing wrong :(
*Could it be a setting in the apache conf? I honestly have no clue on this one
header('Content-Type: image/jpeg');
// Output the image
imagejpeg($img);
You need send header before. But if you want to create the image and show, you need create, and read this for the browser.
readfile($filename);
You can read the man here:
http://php.net/manual/en/function.readfile.php
I use smartReadFile.php from Google Groups to display any type of file.
https://jplayer.googlegroups.com/attach/f308294ddea52f6c/smartReadFile.php?view=1&part=4
It's really smart. =)
<?php
require "smartReadFile.php";
$dir = 'images/';
$filename = 'someimage' . '.jpg';
$location = $dir.$filename;
smartReadFile($location, $filename);
?>
This one is working for me when reading from DB
$image = imagecreatefromstring([path/DBfiels]);
header('content-type: image/jpeg');
imagejpeg($image);
imagedestroy($image);

php GD library Images below a certain size don't show

I'm taking a linked image, and making my own resized versions of them using the imagecopyresampled().
When trying to show GD library resampled images, those below a certain size (around 160px width) show up only as a bunch of gibberish (ex: '����JFIF��>CREATOR: gd-jpeg v1.0 (using IJG JPEG v62), default quality ��C').
I checked the images themselves, and they were stored fine and show up correctly when opened in a picture viewer. However, printing them to browser just doesn't work. When I change the pixel size to a larger pixel size, it works fine.
I'm showing the images in the browser like this
$handle = fopen($fileName, "rb");
$img = fread($handle, filesize($fileName));
fclose($handle);
$imgSize = strlen($img);
$image_type = exif_imagetype($fileName);
header('Content-Type: image/JPEG');
header('Content-Transfer-Encoding: binary');
header("Content-Length: $imgSize");
print $img;
return true;
Right now I'm starting to believe it's something to do with the GD library. Anyone else have any further insight into this?
Thanks.
EDIT:
One of Brad's suggestions showed me the right way. As usual, it was a completely boneheaded mistake. I can't answer my own question yet so I figured I'd make an edit instead.
What I forgot to include in my initial description, was that the previous code was all in one of my models, and I then called a function to show the image in my controller.
I'd recently switched to Symfony2, and have been using the Response return pretty much everywhere in my controllers. However, I'd been reusing my old show image code, which had been written without Symfony. I had a "show image" type of function, which I called in my controller and then returned an empty Response. Thus, Symfony's Response return messed up the encoding. Advanced browsers were able to auto correct for large images, but not for small ones.
My final solution became
In my model
$handle = fopen($fileName, "rb");
$image= fread($handle, filesize($fileName));
fclose($handle);
$image_type = exif_imagetype($fileName);
In my controller
return new Response($image, 200, array('Content-Type' => $image_type));
What you are seeing is the raw image data, which means the browser is, for some reason, not registering the content type.
What I suspect is happening is that whatever browser you are testing with is case-sensitive to the Content-Type header value.
Change image/JPEG to image/jpeg, and see if that works for you.
As for an explanation of why it works with larger images... It is likely that the Content-Type is never being recognized as a known type. Browsers will look at the actual content they received, to try to figure out what type it is. There is probably something in its content sniffing function that looks at small lengths and says, "Nope, probably not an image", and moves on.
they are so many ways to achieve a working script .. i give you 2 examples using file_get_contents and read_file
Example 1 using file_get_contents
$fileName = "http://www.bestmastersineducation.com/teaching-to-tests/standardized-tests.jpg"; // Full path to image
$img = file_get_contents($fileName);
$imgSize = strlen($img);
header('Content-Type: image/jpeg');
header ('Content-Transfer-Encoding: binary' );
header ("Content-Length: $imgSize" );
echo $img;
return true;
See the DEMO : http://codepad.viper-7.com/GFqsLe
Now to Create a smaller sample of the image
header ( 'Content-Type: image/jpeg' );
header ( 'Content-Transfer-Encoding: binary' );
$new_width = 100;
$new_height = 100;
$fileName = "http://www.bestmastersineducation.com/teaching-to-tests/standardized-tests.jpg"; //
$img = file_get_contents ( $fileName );
$im = imagecreatefromstring ( $img );
if ($im !== false) {
list ( $width, $height ) = getimagesize ( $fileName );
$imageSample = imagecreatetruecolor ( $new_width, $new_height ); // new // Height
imagecopyresampled ( $imageSample, $im, 0, 0, 0, 0, $new_width, $new_height, $width, $height );
imagejpeg ( $imageSample, null, 100 );
}
Demo Link : http://codepad.viper-7.com/gXmoDW
Example 2 Using readfile
$fileName = "a.jpg" ; //Full path to image
$imgSize = filesize($fileName);
$imageType = exif_imagetype($fileName);
header('Content-Type:' . image_type_to_mime_type ($imageType));
header('Content-Transfer-Encoding: binary');
header("Content-Length: $imgSize");
readfile($fileName);
Optional
if you want to force download use this instead
$fileName = "a.jpg" ; //Full path to image
$imgSize = filesize($fileName);
$imageType = exif_imagetype($fileName);
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($fileName));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header("Content-Length: $imgSize");
readfile($fileName);
I hope this helps

Categories