I have a php script that gereates image data and uses header() to pretend to be an image. Works great everywhere, except on ipad / iphone safari.
I think because safari does not recognize .php as a valid image type. Fair enough. How do I work around this?
Are you returning the correct image mime type in your php script? E.g.
header('Content-type: image/jpeg');
Remember to put this line before you start writing out the image data.
If you are then I don't know why it wouldn't work (can you post a link to the image?) but another thing to try would be using mod rewrite in your apache .htaccess file to map a.jpg extension to your php script, so it can be accessed using a URL that looks like a regular image.
That would look something like this:
RewriteEngine On
RewriteBase /
RewriteRule ^images/([a-z0-9]+).jpg$ imagescript.php?name=$1
So accessing images/foo.jpg on your server would actually load imagescript.php.php?name=foo
Related
I've noticed in Facebook's source code, that images are links to a PHP file, safe_image.php (or rsrc.php; it changes every now and then), with the name of the selected file appended to the end, such as:
https://external-lax3-2.xx.fbcdn.net/safe_image.php?imagename1234
Or sometimes they're the usual JPEG files with a random token appended to the end:
https://scontent-lax3-2.xx.fbcdn.net/v/t1.0-9/17353408_410522555967800_2778489440067836960_n.jpg?oh=3e00f84c6767364c9304b34f8751114d&oe=5954DA1E
What, I'm wondering is how they get a custom image viewer on their website. Usually, it's just a white background, with the selected image in the top left corner. However, they have it set in the middle with a grey-ish background.
Not only that, the linked image is direct back to the viewed PHP file; how is this possible, and how do they do it?
Cheers.
EDIT: I've also noticed if you change the img src to an invalid link, it will print an error to the page:
The image " Insert image link here " cannot be displayed because it contains errors.
Jpeg files, to no ones surprise, do not take in arguments. However, PHP does. So, what is most likely Facebook did is use a rewrite rule to 'map' their .jpg?= URL to a PHP file, which can process the arguments. That PHP file then fetches the image data from a MYSQL (like) table. If you're wondering, yes you can have the .jpg file extension display in the URL, load data from PHP, and have the image display properly in browser.
This can be achieved via PHP and .htaccess.
Firstly, let's setup our .htaccess inside whatever folder we want to have our /img.jpg?= inside of:
Options +FollowSymLinks
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^img.jpg(.*)$ imageBackground.php$1 [NC]
Yay, now we are mapping our img.jpg?image=bill to imageBackground.php?image=bill.
And then we are going to write our imageBackground.php. I wrote a very simple one, but basically all your doing is setting up headers (for which image format you're using) as well as display the image data. Obviously in practical application this would be more complicated, like maybe you're dynamically grabbing image data from a database (like Facebook).
<?php
if ($_GET['image'] == "bill") {
header("Content-type: image/pjpeg");
echo file_get_contents("bill.jpg");
}
?>
As an example, say I'm trying to download App Icons from the Google Play store for a service. Here is an example URL:
https://lh6.ggpht.com/1eVPA6Iukw-F4i5xq1ZWicaKBzmprLGw98YhdG20E-wlsHHg3PcKJqbY_fWLdJeGRw=w512-rw
There is no mime type associated with the data provided, and when the file is saved any image viewers (or at least the ones I've tried) will say the file is corrupt. They will show up in Chrome and a couple of other things, but when inspecting the data, it's clear there's simply no mime type. This is an issue, because I am further using these data streams in other scripts which require that they be recognized as a specific type. (namely PNG)
I've tried things such as:
imagepng(imagecreatefromstring($icondata), $finaldir.'/icon.png');
Where $icondata is simply a curl response for the image. This will return an error saying that the data is of an unknown format for the imagecreatefromstring function. Of course, I've also tried:
file_put_contents($finaldir.'/icon.png', $icondata);
To no avail. It creates the file, but as I said, the image is not recognized as an image in most applications and in various analyzing functions. Is there a way to specifically set the mime type of a given string of data? Or some other workaround I'm not quite seeing?
Edit: Also, to note, there is nothing wrong with the $icondata variable. I have tried manually saving the image to a file through my web browser, and the same problem arises.
I have developed a small CMS for myself and was facing the same issue. After trying a lot, I have found a solution. It is working for me and I hope you will find it useful for your project too.
Regarding the corruption of file, for Chrome user-agent, Google servers send icons as .webp format and you need a PHP library for handling images of this type. And for other user-agents (like Firefox), images are sent as PNG.
Now comparing the two URLs for a same icon in Firefox or Chrome, you will notice that image paths generated for Chrome contain -rw at the end while the same URL in Firefox doesn't contain that -rw.
Not digging very deeper, simply remove the -rw from the end of the URL and copy the image. You will get a PNG image. A hint is here for you:
<?php
$image_path = "https://lh5.ggpht.com/8PODwBXKk4L201m4IO1wifRDfbn4Q1JxNxOzj-5TXPJ85_S-vOqntLi7TsVyeFQM0w4=w300-rw"; // Firefox app on Google Play
$png_path = substr($image_path, 0, -3);
copy($png_path, 'file.png');
?>
This will save the image as PNG. Please note that I have used substr() function to remove -rw from the end. To make it precise, you may use any other way to fix that part of the path.
P.S. You may also try sending a custom user-agent (i.e. Firefox) with your CURL request to receive the PNG path so you will not need to fix it by yourself :)
You can use HttpResponse::getContentType to determine type of content you're getting from URL
This not a png, but WebP
You can use it in PHP with
imagecreatefromwebp( string $filename );
More information:
- https://developers.google.com/speed/webp/
- http://php.net/manual/function.imagecreatefromwebp.php
I want to have a PNG picture, but when accessing it, it runs a PHP script, the PHP script should decide what picture to send (using some if statements and whatever). Then the PHP script should read the image file from somewhere on my web server and output it.
Here is the issue, if I get a .png file, and put PHP code in it, it won't work, however, if I use the .php extension, it works, and I can even embed the image into other websites, and the PHP can decide what image to send, but if I want to view that image directly (copy it's URL into my address bar) it doesn't work, it gives me the images plain contents (random jibberish).
Anyone know what to do?
Also This is my first question on Stack Overflow - please tell me if I am doing something wrong.
You need to send Content-Type headers.
For png:
header('Content-Type: image/png');
For others change png to jpg or gif or bmp or whatever.
Please note that header() function must be used before anything is written to output.
First, make sure you have your image image.png somewhere accessible to php.
Then create a php script image.php:
<?php
header('Content-Type: image/png');
readfile('image.png');
The script now acts like it was a PNG image.
It sounds like you know how to send the image, your issue is that you want the URL to look like it's a PNG image.
There are a couple of things you can do. First, if your web server supports URL rewriting (like Apache's mod_rewrite module), you can use a rewrite rule so that the user access the script as something like http://example.com/generated_image.png but your server will translate/rewrite this URL to point directly to your PHP script, so something like /var/www/image_generator.php.
Another option would be to actually name your script "generated_image.png" but force your webserver to treat it like a PHP script. For instance, in Apache you could try something like:
<Location /generated_image.png>
ForceType application/x-httpd-php
</Location>
As a final note, if you're not actually worried about the URL, but worried about the file name that is used if the user decides to save it to disk, you can simply use the Content-Disposition HTTP header in your response. In PHP it would look something like this:
<?php
header("Content-Disposition: inline; filename="generated_image.png");
?>
With that, it doesn't matter what the URL is, if the user saves the image through their web browser, the web browser should offer "generated_image.png" as the default filename.
Simplest version I know...
<?php
header('Content-Type: image/png');
if(whatever)
{
$image=your_image_select_function();
}
// as suggested by sh1ftst0rm with correction of unmatched quotes.
header('Content-Disposition: inline; filename="'.$your_name_variable.'"');
readfile($image);
?>
Then, you treat it like an image file. That is, if this is "pngmaker.php" then, in your HTML document, you do
<img src="pngmaker.php">
You can even do
<img src="pngmaker.php/?id=123&user=me">
I'm working on setting up a simple pixel tracking script with PHP, and the below technically works, but when I look at the inspector in Safari I get the following warning (1by1.gif is a 42B gif):
esource interpreted as document but
transferred with MIME type image/gif.
header("Content-type: image/gif");
header("Content-Length: 42");
echo file_get_contents("/path/to/1by1.gif");
// do tracking stuff below here
I've looked at other tracking pixels, and they all show in the inspector as if they are an actual image, even with the .php extension. Any ideas how to fix that warning?
EDIT:
I tried doing the following and I get the same warning:
header("Content-type: image/gif");
$img = imagecreatefromstring(file_get_contents("/path/to/1by1.gif"));
imagegif($img);
You could write 1x1.gif (or some other made up name) in your HTML source and then have Apache actually serve the PHP script. You can do this with .htaccess with something along the lines of:
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^1x1\.gif$ tracking_script.php [NC,L]
This way Safari sees the gif extension and won't complain.
Well this is interesting. If I remove the content-length and just use the following, it appears to work perfectly. Anyone know why that might be?
header("Content-type: image/gif");
echo file_get_contents("/path/to/1by1.gif");
// do tracking stuff below here
I'm a puzzled. Function file_get_contents() is for getting content from a text file. What is your intend here? The function returns the content as string or false. Your echo statement essentially transfers that result which is correctly interpreted as document and not a gif.
Update: Took me a while to even reproduce this and see the warning. Echoing the file_get_contents() shows indeed the gif in the browser, so does a simple include() which also shows the warning. Does this warning causes you any trouble or is this just for a beauty contest? I can only speculate that the Safari's Inspector is a little picky. The same tool in Chrome does not show a warning.
$img = imagecreatefromstring(file_get_contents("/path/to/1by1.gif"));
imagegif($img);
This code
Reads in a GIF image
Passes the image bytes to GD
Asks GD to write a new image.
Many things could go wrong here. For example, writing the image back out might not produce the same exact stream of bytes, maybe more, maybe less. This could make your Content-Length header invalid, and browsers don't like it when you lie about such stuff. Or maybe there's a Notice or Warning in one of the lines, which would be emitted as content before the GIF data. That would certainly look like a "document" instead of as image data to Webkit.
Serving the file through file_get_contents / include / echo eliminates the filter-through-GD step. If the code works properly without that step, the error was somewhere there.
I am trying to display an image from a MySQL blob field. I have tried a few different things and none of them seem to work.
I have tried:
header("Content-type: $type"); img src = $blobData;
header("Content-type: $type"); echo($blobData);
<?php
header("Content-type: $type");
echo $blobData;
?>
This code looks perfectly OK. However, I heard a similar complain from another person and I was able to troubleshoot it by assuring that:
The php script does not output any extra character before or after sending the binary image data.
The php script is saved as a pure ASCII text file, not as a Unicode/UTF-8 encoded file. The Unicode/UTF-8 encoded PHP files might include a signature as the first bytes. These bytes will be invisible in your text editor but server will send these few extra bytes to the browser before the JPEG/GIF/PNG data. The browser will therefore find the wrong signature in the beginning of data. To workaround, create a blank text file in notepad, paste in the php code and save the file in ANSI encoding.
Another option you might consider (assuming you are on Apache):
Create an .htaccess file with a mod_rewrite for all image extensions (png, jpg, gif).
Have it redirect to a php script that looks up the image requested in the DB. If it is there, it echos out the header and BLOG. If it isn't there, it returns a standard 404.
This way you can have:
<img src="adorablepuppy.jpg" />
Which then gets redirected ala:
RewriteEngine on
RewriteRule \.(gif|jpg|png)$ imagelookup.php
This script does a query for the image, which (obviously) assumes that the requested image has a unique key that matches the filename in the URL:
$url = $_SERVER['REQUEST_URI'];
$url_parts = explode("/", $url);
$image_name = array_pop($url_parts);
Now you have just the image filename. Do the query (which I shall leave up to you, along with any validation methods and checks for real files at the address, etc.).
If it comes up with results:
header('Content-type: image/jpeg');
header('Content-Disposition: inline; filename="adorablepuppy.jpg"');
print($image_blog);
otherwise:
header("HTTP/1.0 404 Not Found");
FYI: I have no idea if this would be bad in terms of performance. But it would allow you to do what I think you want, which is output the image as though it were a flat image file on the server using a simple image element. I'm inclined to agree that BLOBs are not the best way to go, but this does avoid any cross-browser issues.
I believe that the issue that you are encountering is an issue with encoding. This resource claims that you can use the print function.
Just get the image from the database. And print it using the correct headers.
$image = mysql_fetch_array(...)
header("Content-type: image/jpeg"); // change it to the right extension
print $image['data'];
For performance reasons... this is not advisable. There are several reasons to put images in databases but the most common are:
a) keeping them indexed (duh!)
You can do this by storing the images flat on the server and just indexing the image filename.
b) keeping the image hidden/protected
Flickr and alike still store the images flat on the server and use a different approach. They generate a URL thats hard to find.
This link points to a protected image on my account. You can still access it once you know the correct URL. Try it!
farm2.static - a farm optimized for delivering static content
1399 - perhaps the server
862145282 - my username
bf83f25865_b - the image
In order to find all my secret images any user can hard hit Flickr with the above address and change the last part. But it would take ages and the user would probably be blocked for hammering the server with thousands of 404s.
That said there is little reason to store images on BLOBs.
Edit:Just a link pointing to someone that explained much better than I did why BLOB is not the way to go when storing images.