I'd like for my app to be able to tell if an image hasn't been viewed in the last 30 days and remove it (along with data in the DB associated with it). I know you can have PHP read and output the image dynamically but I've heard its quite taxing on the system. Is there a way to for me to track these hits even when the image is viewed directly? (would htaccess be able to do this?) Thanks in advance.
For .htaccess something like this...
RewriteRule ^image/(.*)$ image.php?id=$1
And for PHP...
$id = $_GET["id"]; //don't forget to sanitize
mysql_query("UPDATE images SET views = views + 1 WHERE image = '$id'"); //update no of views
header("Content-Type: image/jpeg"); //send image header
readfile($id); //output file to browser
You can parse out the HTTP logs and do this analysis post-factum.
That said, I'd still recommend going with a "dynamic PHP file outputting an image" approach - note that the PHP file can simply stream out a file. Yes, it'll be slower than not going through PHP at all, but it won't be a significant performance hit on your system.
You can create a script that fetches images and pings your database to show that the image has been viewed. By setting the return type of your script to image/jpg you can just use this script instead of accessing images directly:
<?php
//simplified image display script
$imagepath="phpimages/$id.jpg";
$db->pingImage($id);
$image=imagecreatefromjpeg($imagepath);
header('Content-Type: image/jpeg');
imagejpeg($image);
?>
Then use:
<img src='fetchimage.php?id=478' alt='tracked image' />
As far as I know, you'll need to have a database for this.
Sample schema:
Images
id (int, PK)
path (text)
hits (int)
PHP:
// get_image.php
// note, this is just an example and I'm not considering security or hacking attempts
$sql = mysql_query('SELECT * FROM images WHERE id = '.$_GET['id']);
$img
if(mysql_num_rows($img) == 1)
while($row = mysql_fetch_assoc($sql))
$img = $row;
else
// handle some error
mysql_query("UPDATE images SET hit = hits + 1 WHERE id = ".$_GET['id']);
$img = file_get_contents($img['path']);
header('image/jpg');
echo $img;
There could be errors here, I'm just giving you a general idea...
Related
I am using a PHP script that outputs an image, what I am trying to do is track when the image is opened on an email, The code works to display the image but does not run the database query and update the count.
The PHP code as follows.
$image = $_GET['image'];
require_once('connections/site.php');
mysql_select_db($database_site, $site);
$query_requests = "SELECT count FROM tracker WHERE id = '1'";
$requests = mysql_query($query_requests, $site) or die(mysql_error());
$row_requests = mysql_fetch_assoc($requests);
$count = $row_requests['count'];
$newcount = $count++;
$query_update = "UPDATE count SET count = '$newcount' WHERE id = '1'";
$update = mysql_query($query_update, $site) or die(mysql_error());
header("Content-Type: image/jpeg");
readfile('https://mysite.co.uk/images/'.$image);
Maybe I should be using a different method? I was searching around for a way of tracking a standard image open but I couldn't seem to find a decent method so I thought I would try and cook something up to do this.
The problem is that readfile reads and directly writes to the output buffer, hence if you're going to use that method, you'll need to move the readfile to the end of your script.
However, there are a few other concerns:
Your script is using a deprecated database API functions (mysql_*) - you really need to read How can I prevent SQL injection in PHP?
You're potentially exposing other files as you're not attempting to validate what's being fetched via readfile. For example, if $_GET['image'] contains ../connections/site.php, your script will potentially output raw (i.e.: un-parsed) PHP files containing sensitive database settings, etc.) See the existing Preventing Directory Traversal in PHP but allowing paths question/answer for more information.
You're not outputting Content-Type, or Content-Length headers, etc.
put readfile('https://mysite.co.uk/images/'.$image); at the bottom of your code and add this line just before it:
header("Content-Type: image/jpeg");
I have uploaded an Image in my database. The datatype is BLOB. Now I want to view this image in my browser. I have written the following code but its not generating the image. Kindly check it.
Thanks
<?php
include 'connect.php';
//$id= $_GET['product_id'];
$query_images = "SELECT image FROM product_images WHERE product_id=121";
if (!$query_images_result = mysql_query($query_images))
{
echo mysql_error();
}
else
{
$fetch_images = mysql_fetch_array($query_images_result);
$print_images = $fetch_images['image'];
header('Content-type:image/jpeg');
echo $print_images;
}
?>
File 2
<body>
<img src='single_product_image_show.php' alt="image" />
</body>
maybe something like this? You might wanna use base64 encoding to build in the image
FYI: NOT TESTED.
$sql = "SELECT `image` FROM `product_images` WHERE `product_id`=121 LIMIT 1";
$query_images_result = mysql_query($sql);
if (!$query_images_result)
{
echo mysql_error();
}
else
{
list($print_images) = mysql_fetch_array($query_images_result);
$base64source = "data:image/jpeg;base64," . base64_encode($print_images);
echo '<img src="'.$base64source.'" alt="" />';
}
There are multiple possible reasons why this could happen. First try your script directly without "header('Content-type:image/jpeg');" so you can see what it actually returns. Like http://[youhostname]/single_product_image_show.php I assume you will see some errors.
Some best practices to serve images from php:
If you can remove the end php tag (?>). You don't actually need it and you can avoid issues when you have whitespace character after the close tag which will be written to the response and so results as a corrupt image.
You should specify the Content-Length header as well. It's not mandatory but the browser
will know how big the file it has to download.
Specify some cache control headers (https://en.wikipedia.org/wiki/List_of_HTTP_header_fields) so browsers can cache your image so it won't result a full page load and mysql query every time the image appears on the site.
You can store ETag and/or Last-modified in the database which you can retrieve and put in the headers.
I've create a table where I've saved images through "BLOB". I need to show those images along with other items. But I don't know how to show those images together in the same page.
Here's my php code that displays other things in form of a table. Similarily, I wanted to display images accordingly. Any help?
<?php
$display_query = mysql_query("SELECT * FROM eportal");
echo "<table id='pageTable'><thead><tr><th>Item code</th><th>Description</th><th>Cost</th></tr></thead>";
echo "<tbody>";
while($row = mysql_fetch_array($display_query)){
print "<tr><td>".$row['itemid']."</td><td>".$row['description']."</td><td>";
print "₹".$row['cost']."</td></tr>";
}
echo "</tbody>";
echo "</table>";
mysql_close($connection);
?>
Saving images to the DB is not a good idea but if You think You need to it this way, then You can retrieve the data from DB table, encode it to base64 (http://php.net/base64_encode) and then in HTML print it in this way:
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==" alt="Red dot">
Using PHP You would write:
echo '<img src="data:'.$image_mime_type.';base64,'.base64_encode($image_data_from_db).'" alt="My image alt" />';
As other people mentioned, storing the images in the database is usually a bad idea.
Images are not transmitted in the same HTTP response with another page data.
To show images from the database, you would need to implement a script which, given the item id, would read the field and send the image's binary data; and provide the path to the script in your form's <img src="">:
while($row = mysql_fetch_array($display_query)){
print "<tr><td>".$row['itemid']."</td><td>".$row['description']."</td><td>";
print "₹".$row['cost']."</td><td>";
print "<img src=\"image.php?id=".$row['id']."\"></td></tr>";
}
image.php is another script which outputs the value of image_blob given the eportal.id. You would also need to provide correct size and mime type in the headers.
You better just store the images in a file (accessible by the web server) and store the path fo the file in the database.
Read the Blob data and write it into the file with header type image.. and try to print it, It should display the image file.
And yes saving image or any file in DB is really a bad habit as you are increasing DB size and it slowdown the performance also.. I suggest you to just try to convert you Blob into Image but don't apply in your work. Just save the image at desired location and keep its location path into DB to fetch and save next time.
The debate of storing blobs versus storing a path to the image file on disk has been debated over and over again. Microsoft provides a research paper comparing the pros and cons of each here. With that said, to display a blob as an image you need to make a call to a separate page and output header information that tells the browser what type of image is stored.
For example:
connectToDatabase();
$sql = "SELECT image_blob FROM eportal;";
$result = mysql_query($sql) or die(mysql_error());
$row = mysql_fetch_array($result);
header("Content-type: image/jpeg");
echo $row['image_blob'];
$db->close();
In case you still want to save your images in database, you will need second script which will get those images from database and pass them to browser with correct headers.
header("Content-type: image/jpeg");
#
# Replace this with database read:
# readfile('myimage.jpg');
Also, you will need to store what kind of image u use. There will be different header for JPEG, GIF or PNG file.
I know it's not the greatest technique, but coming from Foxpro and Dbase background, some habits just don't die. I am absolutely fresh in PHP and trying to re-create learning curve of my earlier programming experience.
I have drilled GOOGLE for the issue and tried to come up with the script, only issue is sometimes I came up with garbles, sometime empty screen, sometimes only IMAGE.
The scenario is If I am able to create this simple script, I will probably understand how to handle images issue.
I have a database in my MYSQL called crm. In the database I have a table called mast_cust with fields f_name, l_name and pic (BLOB)
I already have some records in them.
What I understood was:
Images and Data (Textual) cannot be printed together
You have to have two scripts , one gathering the image and the other gathering data
The one which gathers data , calls the one which collects images and prints it.
What I want is, to see data in tabular format
First Name | Last Name | Image
These are my two scripts, which is the one which prints garble
Script 1 : Main PHP file - list.php
Script 2 : Image Storing Script: pix.php
list.php
<?php
$errmsg = "";
if (! #mysql_connect("localhost","root","Admin"))
{
$errmsg = "Cannot connect to database";
}
#mysql_select_db("crm");
$strSQL = "select f_name,l_name,pic from mast_cust";
$rsPix = mysql_query($strSQL);
$numRows = mysql_numrows($rsPix);
$i = 0;
while($i < $numRows){
?>
<img src="pix.php?pixID=<?php echo mysql_result($rsPix,$i,"pic"); ?>"/>
<?php
$i++;
}
?>
Script 2 pix.php
<?php
$errmsg = "";
if (! #mysql_connect("localhost","root","Admin"))
{
$errmsg = "Cannot connect to database";
}
#mysql_select_db("crm");
if (IsSet($_GET['pixID'])){
$gotten = #mysql_query("select pic from pix where cust_id = ".$_GET['pixID']);
header("Content-type: image/jpeg");
while ($row = mysql_fetch_array($gotten))
{
print $row['pic'];
}
mysql_free_result($gotten);
}
?>
Any help resolving this issue is highly appreciated.
Thanks and Regards
It seems like you're storing the jpeg image as a blob in mysql.
1.) You can only send one pic at a time. So no need for a for loop.
2.) If so, you'll need to format the output of the data for the pic, so that a browser can read it.
I would recommend against this approach. You should avoid using a relational database for storing images. Try storing the jpegs on a regular filesystem or a file server (like S3), and store the url to it in the database.
If obfuscating the image url isn't enough, try the following approach:
Echo/print a jpg-image with php, for safety?
It uses:
http://php.net/manual/en/function.readfile.php
I'm trying to display multiple images using PHP and MySql database, even if using the while loop I don't get all of the images, I only get one, I mean the first one in the table. What's the problem ?
I'm using a table ID_IMAGE (int, pk, auto increment) and myImage (blob)
$query = mysql_query("SELECT myImage FROM image");
while($data=mysql_fetch_array($query)) {
header('Content-type: image/jpg');
echo $data['myImage'];
}
A possible way to solve this problem is to have a separate script to dynamically output the contents of the image eg. :
image.php
header('Content-type: image/jpg');
// DataBase query and processing here...
echo $data['myImage'];
and call it whenever you need to show images stored in your DB eg. inside your loop:
echo '<img src="image.php?id=' . $data['id'] . '">';
But storing images in the database will take a toll on your server and unless they're really small or you have a good reason to do so, you should only store their physical location on the disk.
You can also use this approach if you wish to hide image location from your users, or control access, but there are better and faster alternatives for that case.
Just to mention the possibility to embed the images directly in html by encoding them, you can use this:
$query = "SELECT myImage FROM image";
if ($result = mysqli_query($link, $query)) {
while ($row = mysqli_fetch_assoc($result)) {
echo '<img src="data:image/jpg;base64,' . base64_encode($row['myImage']) . '">';
}
}
Pro:
The browser does not need to load the images over an additional network connection
You can query and display multiple images in one request
Con:
If the image(s) are big and/or there will be many images, the page will be load slow
Encoding an image to base64 will make it about 30% bigger.
For more information about base encode images:
http://davidbcalhoun.com/2011/when-to-base64-encode-images-and-when-not-to/
base64 encoded image size