How can I compress blob image when retrieving to database? - php

Im using the following code to upload the image in my database:
<form>
<input type="file" name="image">
<input type="submit name="upload">
</form>
<?php
$mysqli=new mysqli("localhost","root","","mydb");
if (isset($_POST['upload'])) {
$photo = addslashes(file_get_contents($_FILES["image"]["tmp_name"]));
$result=$mysqli->query("INSERT INTO images_tbl(image) VALUES('$photo')");
?>
and retrieve the photo this way:
<?php
$result=$mysqli->query("SELECT image FROM image_tbl");
while ($test=mysqli_fetch_array($result)) {
$getphoto = $test['image'];
}
echo'<img src="data:image/jpeg;base64,'.base64_encode($getphoto).'" style="width: 40px; 40px;" class="w3-round" draggable="false" /> ';
?>
When I upload a large image it loads the original file size. I want to optimize my website. Is there any way to compress the image when I retrieve them to the database so it loads faster to the website?

I would suggest not adding images to the database. At least not a MySQL database.
Instead, try to store images in the filesystem and only store the filesystem path in the database.
Consider renaming the files to long unique random names and storing that along with the original filename in the database.
Using PHP you can serve your files using their original names:
header('Content-Type: image/jpeg');
header('Content-disposition: attachment; filename="'.$filenameOriginal."\n");
readfile($filenameStorage);
MySQL is great att manipulating text, large blobs of binary data are a different story though. You should also ask yourself what you are gaining by storing images in the database.
About compression. Images are commonly compressed quite well so further compressing them for database storage is usually not feasible.
I would also strongly urge you to look into Prepared Statements for MySQL.
https://www.php.net/manual/en/mysqli.quickstart.prepared-statements.php
That allows you to use queries like:
INSERT INTO images_tbl(image) VALUES(?)
The question mark signifies a variable which you pass to MySQL as binary with a separate function. This prevents SQL injection attacks which addslashes() definitely will not.
https://www.php.net/manual/en/mysqli-stmt.bind-param.php

Related

display image stored in database

I have images that are base64 encoded as blobs in my sql database.
using a php script I can properly display the picture in my browser using.
echo '<img src="data:image/jpeg;base64,' . $fetch_row['object']. '" />';
however, I would like to create a view that would display the photo directly or by accessing the php file and returning the picture in a column. I have tried using something like: in mysql
concat('<img src="data:image/jpeg;base64,',`object`,'" />')
or concat('<img src=/image.php? blah blah blah)
any ideas?
<?php
header('Content-type: image/jpeg');
echo base64_decode($fetch_row['object']);
Your question also exactly typifies why storing images in the database is a BAD idea. If the image was just a file on your server's drive, you could just have
<img src="/path/to/file.jpg" />
and not have to involve the DB/PHP layer at all. As it stands now, your data-uri version prevents the browser from caching that image at all, and you'll be forcing the user to download that image EVERY time, burning up their (and your) bandwidth.

PHP: Storing picture in the file directory, image name in db and retrieving an image

After doing research, I found that it is more recommended to save the image name in database and the actual image in a file directory. Two of the few reasons is that it is more safer and the pictures load a lot quicker. But I don't really get the point of doing this procedure because every time I retrieve the pictures with the firebug tool i can find out the picture path in the file directory which can lead to potential breach.
Am I doing this correctly or it is not suppose to show the complete file directory path of the image?
PHP for saving image into database
$images = retrieve_images();
insert_images_into_database($images);
function retrieve_images()
{
$images = explode(',', $_GET['i']);
return $images;
}
function insert_images_into_database($images)
{
if(!$images) //There were no images to return
return false;
$pdo = get_database_connection();
foreach($images as $image)
{
$path = Configuration::getUploadUrlPath('medium', 'target');
$sql = "INSERT INTO `urlImage` (`image_name`) VALUES ( ? )";
$prepared = $pdo->prepare($sql);
$prepared->execute(array($image));
echo ('<div><img src="'. $path . $image . '" /></div>');
}
}
One method to achieve what you originally intended to do by storing images in database is still continue to serve image via a PHP script, thus:
Shielding your users from knowing the actual path of an image.
You can, and should have, images stored outside of your DocumentRoot, so that they are not able to be served by web server.
Here's one way you can achieve that through readfile():
<?php
// image.php
// Translating file_id to image path and filename
$path = getPathFromFileID($_GET['file_id']);
$image = getImageNameFromFileID($_GET['file_id']);
// Actual full path to the image file
// Hopefully outside of DocumentRoot
$file = $path.$image;
if (userHasPermission()) {
readfile($file);
}
else {
// Better if you are actually outputting an image instead of echoing text
// So that the MIME type remains compatible
echo "You do not have the permission to load the image";
}
exit;
You can then serve the image by using standard HTML:
<img src="image.php?file_id=XXXXX">
You can use .htaccess to protect your images.
See here:
http://michael.theirwinfamily.net/articles/csshtml/protecting-images-using-php-and-htaccess
I'm also working on a project which stores the url path of images on the database (Amazon RDS) and the actual images in a cloud managed file system in Amazon S3.
The decision to do so came primarily with the concern of price, scalability and ease of implementation.
Cheaper: Firstly, it is cheaper to store data in a file system (Amazon S3) compared to a database (Amazon EC2 / RDS).
Scalable: And since the repository of images may grow pretty big in the future, you might also need to ensure that you have the adequate capacity to serve them. On this point, it is easier to scale up a filesystem compared to a database. In fact, if you are using cloud storage (like Amazon S3), you don't even need to worry about having not enough space as it has been managed for you by Amazon! you would just need to pay for what you use.
Ease of Implementation: In terms of implementation, storing images in a file system is much easier. If you were to serve images directly from databases, you would probably need to implement additional logic to convert blob files into html src blob strings to serve images. And from the look of it, this might actually take up quite substantial processing power which might slow your web server down.
On the other hand, if you were to use a filesystem, all you would require is to put down the url path of the image from the database to the src attribute of the image and its all done!
Security: As for security of the images, i have changed the image name to a timestamp concatenated with a random string so that it will prove really difficult for someone to browse for pictures without knowing the file name.
ie. 1342772480UexbblEY7Xj3Q4VtZ.png
Hope this helps!
NB: Please edit my post if you find anything wrong here! this is just my opinion and everyone is welcome to edit!

In PHP, how I show various images from a BLOB field in the database with the HTML content?

I stored it images in the database using an BLOB field (I'm using SQLite). Now I want to recover this image to a HTML page and show the images there.
I can retrieve the binary data from the image from the database, but what I can do to transform this data in an image and show in the page? Currently I want to show the images inside a field in a table.
You could abuse the data: protocol, but trust me, you don't want that if you can avoid it. Normally, you create a separate php-script that serves images, so in script 1:
<img src="/myimagescript.php?id=1234">
In myimagescript.php:
//get the data from the database somehow (mysql query et al.)
//let's assuma the data is in $data
header('Content-Type: image/jpeg');//alter for png/gif/etc.
echo $data;
#uscere90 is right, but an example might help (example of a PNG image):
<?php
header("Content-type: image/png");
echo $image_data;
?>
Typically this is done by creating a wrapper script or function that retrieves the BLOB and delivers it with the appropriate content headers to be used as an <img src=''>
Doing it this way also gives you the benefit of being able to deliver or not deliver the image based on other authentication factors determined by your PHP. If, for example, a user doesn't have permission to see an image, you can instead show some default or blocking image in its place.
// File getimg.php
// Retrieve the image blob specified by $_GET['imgid'] from the database
// Assuming your blob is now in the variable $image...
header("Content-type: image/jpeg");
// Just echo out the image data
echo $image;
exit();
Now in your html:
<img src='getimg.php?imgid=12345' alt='this is your img from the database' />
You can create a simple image.php page that queries your database, then prints out a content-type relevant to the image and vomits the binary data to screen. So, in your table, you'd have <img src=image.php?id=something />, and then you'd use that id in your image.php page to do your database lookup, retrieve the binary data, and print it to screen after printing the content-type header.
image.php:
<?php
header('Content-type: image/jpeg');
//DO SQL NINJA STUFF HERE
echo mysql_result($result,0,"file_content");
?>
There are two options I would say:
You create a script that returns the image data. The <img src="-field then calls that script.
You offer the data of the images directly via a data url.
Both have it's pros and cons. For the first solution you must create a new script for the images. The second method will bloat your page if the images are large.
As there are examples for the image script method already, here is some code fragment for data URIs:
<?php
function data_uri($content, $mime)
{
$base64 = base64_encode($content);
return ('data:' . $mime . ';base64,' . $base64);
}
?>
<img src="<?php echo data_uri($content,'image/png'); ?>" />
You need to set the mime-type according to your image, image/png for PNG images, image/jpeg for JPG files etc., see here for a list.

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.

PHP - Store Images in SESSION data?

Can you store an image in a PHP SESSION ?
I have a multi-step registration process using PHP on my site. On one of the steps, the users can upload their company logo (image).
The last step is to process their credit card.
So before I write any images to the web server and image location to the database, I want to make sure their credit card is valid and process.
As such, is it possible to temporarily store that image data in the SESSION variable?
If not, how else do people temporaily store image data on forms before committing that data?
You can but expect memory usage of your session to increase depending on the size of the images. In order to do so, you must save the file contents into a session variable.
If it is in session data and you have multiple steps after the upload the image will be reloaded (into the session) every page view until the steps are complete.
I would personally recommend against using the session for holding a binary file. Saving the image on disk into a temporary location until the registration is complete. I would only save the path to the temporary file in session. When the transaciton is completed move it to a proper location and do your db inserts.
Also, in essence, session data is stored on disk (or db) anyway so you might as well save the image file once then issue a move command once complete.
I'd save the file to disk, you could even name it using the user's session id. Then there could be some sort of clean up script which is run as a cron job and deletes the images of people who never successfully paid.
If you try and store an image in the session, you're doing it wrong.
When a file is uploaded, it gets assigned a temporary name in the $_FILES array. I don't know the exact lifespan of those files, but you might be able to capture that name in the session and put off the move_uploaded_file() call until after the CC is verified.
Or, you could do the CC step first.
Yes, you can store an image in a PHP session. Get it into PHP as a string (i.e. binary data) and then you can put it in the session.
You will want it to only be as big as it needs to be and you need to delete it as soon as you don't need it because large pieces of information in the session will slow down the session startup.
Sometimes We need to preview/confirm page before save data into database.
But Image file to the confirm page is a little bit differnt.You cant do
$_SESSION['s_name'] = $_FILES['f_name'] coz SESSION just keep the text file.
In the alternative way keeping file contents/binary value in session.
$_SESSION['obj_image_session'] = file_get_contents($_FILES['image_name']['tmp_name']);
$file= "new_file.jpg";
$fp=($file,"w");
fwrite($fp,$_SESSION['obj_image_session']);
If you have to keep the data, I would suggest keeping it as base64_encoded string. You can directly send base64_encode image data to the browser.
If I'd be in similar situation i would have rather saved the image and kept the information about the image in session/db. If for some reason the registration fails, i would unlink the file later. and occasionally run cron jobs to locate missing links with the images.
But i will really suggest you to stick to the second option and avoid the hassle altogether.
You can store image data in session as base encoded one easily. In production server you are supposed to have enough RAM.
My application needed upto 40MB of 4 images/apps for update and change before putting in mongoDB.
(Base encoding makes 1.3 times larger image size.)
$tmpNameSS1 = $_FILES["screenshot1"]["tmp_name"];
$fp = fopen($tmpNameSS1, 'r');
$rawDataSS1 = fread($fp, filesize($tmpNameSS1));
fclose($fp);
$SS1FileName = $_FILES["screenshot1"]["name"];
$encodedSS1Data = base64_encode($rawDataSS1);
registry::update('sCreateSS1Name', $SS1FileName);
registry::update('sCreateSS1Data', $encodedSS1Data);
A case will be: you have multiple image to uploaded and both client and server validation for size and type. It is faster to fetch from session.
After putting in DB null the variable holding the image.
Browser will show show that image with:
<img src="data:image/;base64,<?php echo registry::get('sCreateSS1Data'); ?>"/>
You can update the session for the image with empty string after the code reaches the end of the block. Typical case is updating form field with validation and when the user wants to change the text. You also want to show what image was uploaded between those failed updates. If you want to save the round trip (advisable) keep data for some moments in the session and empty that value after code is about exit.
when you put a file type in your form, you need to use the global variable Files
form.html
<form action="process.php" method="post" enctype="multipart/form-data">
<label for="picture">Picture:</label>
<input type="file" name="picture" id="picture"><br>
<input type="submit" name="submit" value="Upload">
</form>
process.php
<?php
session_start();
//make sure you have created the **upload** directory
$filename = $_FILES["picture"]["tmp_name"];
$destination = "upload/" . $_FILES["picture"]["name"];
move_uploaded_file($filename, $destination); //save uploaded picture in your directory
$_SESSION['user_name6'] = $destination;
header('Location: display_picture.php');
?>
display_picture.php
<?php
session_start();
?>
<div>
<img src="<?php echo $_SESSION['user_name6']; ?>" alt="picture"/>
</div>

Categories