Server generated dynamic image and long URL - php

I need to display an image that is generated by the server. It is generated based on parameters supplied via URL. Problem is, parameters can be very numerous and long and as we know there is a limit to GET request length.
Here is a simplified version of the code:
View:
<img alt="Preview" src="/preview/getPreview/?id=1&page=1&values=%7B%22object_82%22%3A%22Test%22%2C%22object_83%22%3A%22Test2%22%2C%22object_84%22%3A%22Test3%22%7D&size=676">
This is a very short list of parameters there will be much more. As you can see values is actually a JSON stringified array.
The controller part of the code is more or less like this (not sure if it's actually relevant to the question but still here it is):
function getPreview() {
$buffer = createImageFromData($id, $page, $values, false);
$img = new Imagick();
$img->setResolution(300, 300);
$img->readimageblob($buffer);
header("Content-type: image/jpeg");
header("Content-Length: $lenght");
header("Content-Disposition: inline; filename=preview.jpg");
echo $img;
}
So the question is - how to display server generated dynamic images without having to do the src='' part that will simply get too long for some images.

If you have a lot of information that you need to pass to the server. A get request is going to run out of space on older browsers fast: maximum length of HTTP GET request?
What you could do is using javascript, post the information to your server first before you show the image. If you would like to save the data to a database an return an ID that would be a good solution, you can then load the image with:
<img src="/preview/getPreview/?id=312">
If you do not want to save the data you could return a base64 encoded image directly, this isn't supported in < IE8 very well though. A response could look like:
<img src="data:image/gif;base64,R0lGODlhDwAPAKECAAAAzMzM/////wAAACwAAAAADwAPAAACIISPeQHsrZ5ModrlN48CXF8m2iQ3YmmKqVlRtW4MLwWACH+H09wdGltaXplZCBieSBVbGVhZCBTbWFydFNhdmVyIQAAOw=="alt="Base64 encoded image" width="150" height="150"/>
I mentioned that you should post via javascript so the generation wouldn't have to reload the page. This however is something you do not have to do.
Also - If you are generating the same image over again. We have experienced large page loading times due to the image creation script - So would suggest to cache the image if you can.
Maybe if you update your question to specifically state what your intentions are and what images you are trying create, I could taylor this answer better.

Related

How to show image hidding its direct link in php?

How can I create a php code that will process an ID for example and return corresponding image without providing client with actual image hotlink.
As implemented on link below the image is displayed in html page, but the hot link is hidden from client. Even opening the image in new window same link is shown not the original link to image.
This is definitely not implemented in .htaccess file as for each image URL with id corresponding image is rendered and is not a redirect to a single page.
http://www.imagesup.net/?di=15140291437113
a basic way could be something like this
<?php
// query to database mabye?
$myPath = getImagePath($_GET['id']);
// what kind of image file is that?
$contentType = getContentType($myPath);
// read file content
$img = file_get_contents($myPath);
// here you tell the browser what kind of image is that e.g. jpeg,png,gif...
header("Content-Type: $contentType");
echo $img;
?>
you need to define getImagePath and getContentType functions according to your needs.
Whenever a surfer enters one of my websites, I always assign a session to him. The session holds a couple infos, for example: agent, IP, language, date, … etc., and gets passed along via cookie or via GET (as parameter to each one of my pages).
Since I deal with a lot of image content, I started databasing my collection. Which basically means that for administration and clustering purposes, I am saving all my images to a SQL database which is multi-homed and spread accross several servers. One could argue if that is a smart thing to do, but we can argue that on another day and in another article.
I wrote a little script which is used throughout my site:
<img src="http://example.com/display.php?id=34" border="0" alt="" />
With an ever changing ID of course. That’s the part referencing my images in the database.
The following is the code from the script which I use to retrieve the image from the database:
<?php
$connection=#mysql_connect(...);
#mysql_select_db(...);
$query="SELECT mime, file FROM images
WHERE id=".$_GET["id"];
$rawdb=#mysql_query ($query,$connection);
if($rawdb AND #mysql_num_rows($rawd-->0){
$array=# mysql_fetch_array($result);
if (!empty($array["fileContents"])){
// Output the MIME header
header("Content-Type: ".$array["mime"]}");
// Output the image
echo $array["file"];
}else{
// something else...
}
#mysql_free_result($rawdb);
}else{
// something else...
}
#mysql_close($connection);
?>
Since I already have a session for each user that comes to my website, I just added the following:
<img src="http://example.com/display.php?id=34&sid=383829" border="0" alt="" />
And implement a small session checkup in the script itself:
<!--
session_start();
if($_SESSION["is_known"]){
// do database calls
}else{
header("Location:http://mydomain.tld/dontsteal.html");
}
-->
The main advantage to my method is, that the session is entirely server side. A user can not rid himself off it, or fake information. Since I have a timeout and save all the necessary info (IP!) to validate against, it looks pretty perfect to me and fit my needs.
One of the setbacks here are resources and performance. But since I am not forcing you, you may test and evaluate. Hope that helps!
Create a php script which you use as src in the img tag.
In that script get the data from the image with file_get_contents. Then send the header with the right mime type. For example header('Content-type: image/jpeg'); Then output the data.

Google Contact API Picture Data, returns data, but I dont know how to display it with PHP

I am using OAuth 1.0, I am getting the contacts just fine. Next I fetch an image using the link that is in the contact info. If the user has an image the request works and return a bunch of data. When I echo it I get something like this:
"" ÿÀ``"ÿÄÿÄ<!"12A#Qq‘BRa3‚’±Ñðbrƒ¡Â$%¢³ÿÄÿÄ#!1Q"AaqÿÚ?ôÌìç™pzõWoÂ~vïD±èÐvQNl/žåÐìMCÀƒÚüü¿ ÔLß÷&‹ðKš×aG¥=Ë È
Which I am assuming is the data for the image. Now that I have this, I cant figure out a way to display it.
here is an example of what I am doing:
$consumer = new OAuth($key,$secret);
$image = $consumer->fetch($theImageUrl);
return $image;
The request is working, theres no 400,401, or 404 errors.
I tried doing this already:
<img src="/art/transperantimage.png" style='background: #fff url(data:image/png;base64,<?=$image ?>) repeat-x bottom'/>
and I just ended up with more data jibberish.
I guess my question is how the heck to I display this data?
Per the documentation, this request returns the bytes of the image. So you have three options:
Write a PHP script that outputs those bytes (and only those bytes) directly to the client using the appropriate Content-Type header, which is what #Prowla has in mind. Then point to this script in your <img src="...">.
Write the bytes to a publicly-accessible file on your web server, and then put the URL of that file in your <img src="...">.
Use a data URI, which you seem to have attempted, but forgot that you need to Base64 encode the data first, e.g.:
<img src="data:image/jpeg;base64,<?php echo base64_encode( $image ); ?>" />
While #3 is looks the simplest, #2 is probably the best solution since the image likely doesn't change very often so there's no sense requesting it from the API every single time someone reloads your page. You can just write the image to a file if the file doesn't already exist, and then periodically (e.g. every day or week) check to see if there is a new image and if there is, overwrite the old one.
Before printing out the image set the header content type to something like (depending on the data type):
header('Content-Type: image/jpeg');

Inline generated images exceeding length

I am using PHP to generate images and this works fine. I am having trouble displaying these images however:
My image generator is a PHP file that takes tons of parameters and loads of data to generate the image. Because of the excessive amounts that has to be passed to the generator, using the GET container does not work for me, so the data is sent via a POST request. The result of this request is the raw image data.
I am using
$result = post_request('http://myurl.com/graphx/generator.php', $data);
if($result['status'] == 'ok') {
echo "<img src=\"data:image/png;base64,".
base64_encode($result['content'])."\"/>\n";
}
to display my image. This works for very small images, but as they get bigger (300px*300px for example), the image is not displayed anymore (it seems to be cut somewhere).
Is my approach reasonable?
Is there any workaround for the size issue?
Update:
When I let the generator save the image to a file, the created file contains the image as I want it to be. Also, if convert my generator into a GET-generator, the following code works properly as well:
$data = http_build_query($data);
echo "<img src=\"http://myurl.com/graphx/get_generator.php?{$data}\"/>\n";
So it definitely seems to be a problem with either the POST request, or the conversion into the base64 format. I'm using the POST request as shown here.
I'd suggest having your page be structured like this:
main page:
<img src="imageproxy.php" />
imageproxy.php:
<?php
$result = post_request('http://myurl.com/graphx/generator.php', $data);
header('Content-type: image/png');
if($result['status'] == 'ok') {
echo $result['content']);
} else {
readfile('error_message_image.png');
}
instead of trying to work with data uris and length limits, just have your proxy script output the actual raw image data and treat it as an image in your client-side html.
According to http://en.wikipedia.org/wiki/Data_URI_scheme IE 8 (and presumably below if they support it) "limits data URIs to a maximum length of 32 KB". This could be what you are seeing if it only reads the first 32k of whatever you are sending it.
Why don't you base64 the parameters and put THAT in the GET request, and do a simple:
<img src="/path/to/php.php?p=eyJ0aGlzIjoiaXMiLCJhIjoiYmVhdXRpZnVsIiwic2V0Ijoib2YiLCJwYXJhbWV0ZXJzIjoiISEifQ==" />
Then on the php.php base64_decode($p) and return the image.
Even better on php.php, use X-Sendfile mod of apache (https://tn123.org/mod_xsendfile/) and perhaps cache the image as well locally so that you don't have to recreate it all the time
Edit:
I don't know exactly how many parameters we are talking about here. If you go and see What is the maximum length of a URL in different browsers? you will see that experience has shown that a URI is pretty much around 2000 characters.
So it depends if your base64 encoded string is less that that you are safe. Otherwise you could think of alternative ways of encoding. Perhaps yEnc or base85?
Even further you could do store a serialized object (containing the parameters needed) on a local storage (ie RDBMS), link it with an id and pass that id around. When php.php get's the id, looks it up on the storage retrieves the parameters creates the image and so on.

How to display an Image from a mysql blob

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.

How to load dynamic image w/php gd library, w/o saving it on server or having src="script.php"?

I would like to generate a dynamic image from a script, and then have it load to the browser without being persistent on the server.
However, I cannot call this by setting the image's src="script.php", since that would require running the script that just generated the page and its data all over again, just to get the final data that will generate the graph.
Is there a way to do this that is similar to setting image's src="script.php", but which is called from within another script, and just sends the image without saving it? I need access to the data that is used in the generation of the markup, in order to create this dynamic image.
Or, if not, what is the easiest way to destroy the image once the page is loaded? a quick ajax call?
Is there any way to cache certain data for some limited time frame in order for it to be available to some other script?
Any ideas would be greatly appreciated, as I'm having a really hard time finding the right solution to this...
Thanks!
You can inline the image into a <img> tag if you need to.
Like
<?php
$final_image_data; // Your image data, generated by GD
$base64_data = base64_encode($final_image_data);
echo "<img src=\"data:image/png;base64,{$base64_data}\" ... />";
?>
That should work on all modern browsers, and IE8. Doesn't work well with some email clients tho (Outlook, for one).
Also, another solution I found is to store the image in a session variable which is then called from a php script in the image tag. This would allow a user specific image to be served, and then removed from memory by the script... This also avoids messy img src="" tags...
Hopefully that is helpful to someone.
Use a rewrite rule.
RewriteRule ^magicimage.jpg$ /myscript.php
Then simply echo your image data from gd, instead of writing it to disk -- which is as simple as not providing a filename to the appropriate image*() function
myscript.php
<?php
$im = imagecreatetruecolor($w, $h);
//...do gd stuff...
header('Content-type: image/jpeg');
//this outputs the content directly to the browser
//without creating a temporary file or anything
imagejpeg($im);
And finally, utilize the above
display.php
<img src="magicimage.jpg">

Categories