Display an image (tinyblob) stored in a database with php - php

I try to read image from database (blob) but i have problem becouse i don't know mime type of image. I have only tinyblob.
Can i read image and save it back to my hard disk?

The best solution is to store the mime-type in the DB at the same time you're inserting the image into the blob field. Otherwise you're going to have to the following EACH TIME the image is retrieved:
$image = $row['imageblob']; // $row = result row from DB query.
$finfo = new finfo(FILEINFO_MIME);
$mime_type = $finfo->buffer($image);
This gets to be expensive very quickly on a busy system, so best do the determination ONCE and then store that result.
Relevant PHP docs here.

Why not store the images on the hard disk all the time, and store in the Database a relative link based on a known directory?

Here's some code that I have used to get a logo (blob) from a mysql database
<img src="data:image/png;base64,<?php echo base64_encode($MyClass->getLogo())?>" alt="Logo" width="233" height="65" />
And the getLogo() function
public function getLogo()
{
if ($this->getId())
$query = "SELECT `logo` FROM Logos WHERE `logo_id` = '{$this->getId()}' LIMIT 1";
else
$query = "SELECT `logo` FROM Logos WHERE `logo_id` = '1' LIMIT 1";
$result = mysql_query($query);
if ($result)
$row = mysql_fetch_array($result);
else
return NULL;
return ($row['logo']);
}

Related

How can I pull a random image from MySQL with PHP?

I'm learning PHP/MySQL while working on a web app. Part of this app calls for echoing out a random image from an image directory titled 'htdocs/full'. The database is holding the path to each image in a column titled 'image_path' in addition to columns for 'first_name' 'last_name'.
I'm able to make it call a random row from the database and I can make it display literal data from the 'first_name' and 'last_name' columns. But I'm struggling to make it take the path from the 'image_path' column and converting it into an image rather than a literal.
I've been experimenting with a number of methods over the last 24 hours, but most everything else I've been seeing on Stack and Google is for pulling an image straight out of the directory without using the database row (which is needed due to the corresponding 'first_name' and 'last_name').
Here is what I have so far (although I also have many different variations, this I think is the closest I've come):
<?php
$username="root";$password="*********";$database="offenders";
mysql_connect('localhost',$username,$password);
mysql_select_db($database) or die( "Unable to select database");
$sSQLQuery = "SELECT image_path FROM offenders ORDER BY RAND() LIMIT 1";
$aResult = mysql_query($sSQLQuery);
WHILE($aRow = mysql_fetch_array($aResult)):
{
header("Content-Type:image/jpeg");
echo "<img src='php/imgView.php?imgId=".$aRow['image_path']."' />";
}
ENDWHILE;
?>
It produces a page with a tiny broken image at the top left. I've tried this with echoing $aRow as well as $aRow['image_path'] as seen above and a number of other tweaks that seems to cause error. Any ideas what I'm doing wrong?
Thanks a lot!
Updated code:
<?php
$username="root";$password="*******";$database="offenders";
mysql_connect('localhost',$username,$password);
mysql_select_db($database) or die( "Unable to select database");
$src="full/";
//if you have any problem in the solution check this line,
//means weather you are providing right path for your files or not.
$sSQLQuery = "SELECT image_path FROM offenders ORDER BY RAND() LIMIT 1";
$aResult = mysql_query($sSQLQuery);
$aRow = mysql_fetch_array($aResult);
$file_path=$src.$aRow["image_path"];
//echo "<a href='php/imgView.php?imgId=".$aRow['image_path']."'>"."<img src=".$file_path." />"."</a>".'<br/>';
echo "<img src=".$file_path." />".'<br/>';
//echo "<img src=full/1b2ba2f9a8b8ee9c062b09767535d69bd954e125.jpg>";
/* if(isset($_GET['imgId']))
{
//i am query only first_name but you can add for field as you want
//and i also used $_get['imgId']; in the query which is not safe but you can make it for //secure.
$sSQLQuery = "SELECT first_name FROM offenders where image_path='".$_GET['imgId']."'";
$aResult = mysql_query($sSQLQuery);
WHILE($aRow = mysql_fetch_array($aResult)):
{
echo $aRow['first_name'];
}
ENDWHILE;
}
*/
?>
There are several things wrong here.
You have your database output in a loop. Instead of
WHILE($aRow = mysql_fetch_array($aResult)):
{
...
}
ENDWHILE;
use:
$aRow = mysql_fetch_array($aResult);
...
You are returning what looks like HTML, but you have a content type of JPG. Either return HTML and use an appropriate content type or return a JPG, and return that.
If you want to return the JPG itself (and not the HTML), use CURL to grab the write image and return it.
In my view i dont know why you are running the while loop because in your query you have limit of one so you dont have to run the while loop.
lets say you have your images in the folder name php/image/than your images comes
I am writing my solution on the assumption that your images are in the image folder, if they are not you can simply change the $src value in the solution.
and i am also thinking you want to use these images as a link, so you can get the first_name, and last_name when some one click on the image, reason i am thinking like this, that you try to give id in the img src="",
any way i am writing two solution see which one work for you. first one gonna make them link and second one only gonna pull the images from the database.
First one on the assumption you want to pull the first_name and last_name, from the database, when some one click on the image.
<?php
$username="root";$password="";$database="offenders";
mysql_connect('localhost',$username,$password);
mysql_se
lect_db($database) or die( "Unable to select database");
$src="php/image/";//if you have any problem in the solution check this line,
//means weather you are providing right path for your files or not.
$sSQLQuery = "SELECT image_path FROM offenders ORDER BY RAND() LIMIT 1";
$aResult = mysql_query($sSQLQuery);
$aRow = mysql_fetch_array($aResult);
$file_path=$src.$aRow["image_path"];
echo "<a href='php/imgView.php?imgId=".$aRow['image_path']."'>"."<img src=".$file_path." />"."</a>".'<br/>';
if(isset($_GET['imgId']))
{
//i am query only first_name but you can add for field as you want
//and i also used $_get['imgId']; in the query which is not safe but you can make it for //secure.
$sSQLQuery = "SELECT first_name FROM offenders where image_path='".$_GET['imgId']."'";
$aResult = mysql_query($sSQLQuery);
WHILE($aRow = mysql_fetch_array($aResult)):
{
echo $aRow['first_name'];
}
ENDWHILE;
}
?>
Second solution only pull the images from the database
remove the isset condition and while loop in the isset condition.
and change this line
echo "<a href='php/imgView.php?imgId=".$aRow['image_path']."'>"."<img src=".$file_path." />"."</a>".'<br/>';
To
echo "<img src=".$file_path." />".'<br/>';
//if you notice the only different is this that i
//remove the <a> tag in its path, so not it gonna pull images
// from the database but you cant use them as link.
Thanks
this solution work fine if it does not please post your folder structure, means where you have images and this file imgView. and second note i removed your while loop from the solution,
//

php image blob wont show

So I am trying to show an image from my mysql database. The image is saved as a blob format. I made seperate php file for fetching the image. I then call this file from where I want to show the image like so:
<img src="image.php?id=3" />
This is the file that fetches the image:
<?php
require 'scripts/connect.php';
if(isset($_GET['id']))
{
$id = mysql_real_escape_string($_GET['id']);
$q = $db->prepare("SELECT image FROM products WHERE id = '$id'");
$q->execute();
$data = $q->fetch();
header("content-type: image/jpeg");
echo $data["image"];
}
?>
But when I try and run this code no image shows up. Instead I get this annoying broken link image thing:
http://i.imgur.com/NQOPSAf.png
Your code doesn't do what you expect.
Try to change
$q = $db->prepare("SELECT image FROM products WHERE id = '$id'");
in - if id field is numeric one; if isn't, add single quote -
$q = $db->prepare("SELECT image FROM products WHERE id = $id");
Your example didn't work as you were passing to query $id placeholder and not his value (you dind't concatenated it)
Of course with that method you're not save by SQL Injection at all, so you should use pepared statement that way
$q = $db->prepare("SELECT image FROM products WHERE id = :id");
$q->execute(Array(":id" => $id));
Edit
As OP told me that $data['image']; is a bitstream, I will suggest to use something like:
echo '<img src="data:image/jpg;base64,'. base64_encode($data['image']). '" alt='imagename'>;
or if your echo goes directly into src attribute:
echo 'data:image/jpg;base64,'. base64_encode($data['image'])
Try to replace
header("content-type: image/jpeg");
with
header("content-type: image/png");
Try,
$query = $db->prepare("SELECT image FROM products WHERE id = :id");
$query->execute(array(":id" => $id));
$data = $q->fetch();
For serving the image, use
$mime = pathinfo($data['image'], PATHINFO_EXTENSION);
header('Content-Type: '.$mime);
ob_clean();
flush();
readfile($data['image']);
Note:
readfile() needs the image path to where the images are stored.
if you are use PHP >= 5.4, $query->execute([":id" => $id]);
can be used instead of
$query->execute(array(":id" => $id));

Insert images (NSData) into BLOB fields

From iOS app to php script, I want to store a bench of images as BLOB types:
$profile_images = $_REQUEST['profile_images_array'];//get the array of images
//loop the images and store them one by one
foreach($profile_images as $image){
$sqlinsertimages = "insert into profile_images (id_client,image) Values ('".$id."',mysql_real_escape_string('".$image."'))";
$result = mysql_query($sqlinsertimages);
}
The insert would work fine if I eliminate the image field (which is BLOB type), so the issue is obviously with the saving BLOB types in the table.
How to store properly the images in PHP as BLOB?
PS: not willing to adopt the file system storage.
Ok, I guess that work finally, didn't knew that I had to save the image to the server before saving it to MySQL:
foreach($profile_images as $image){
//Get the file as a string before inserting it to table
$content = file_get_contents($image);
$content = mysql_real_escape_string($content);
$sqlinsertimages = "insert into profile_images (id_client,image) Values ('".$id."','".$content."')";
$result = mysql_query($sqlinsertimages);
}

Save image URLs in MySQL?

I actually have a few questions here: My end goal is to write a script that will automatically display all the images that i have saved inside my database(If i add new images to my database(image URLs), each time i refresh the page i would like those "new" images to be instantly displayed as well).
What is the proper way to save an image URL inside MySQL? Currently i set my input type to VARCHAR; is that okay for image URLs?
Also, at the moment i'm working with WAMP server just to test how the site is working; so i put an image inside the www folder(within the same folder as my php script) and inside the database table i simply put the URL as follows: image.png is this the correct way to enter an image URL inside my database?
What is the best way to display these images in a sequence? The following code is what i have so far:(the image widths will take up about 70% of the page so the images will not be next to each other; they will be in a column form.)
<?php
$db_host="host";
$db_user="user";
$db_pass="pass";
$db_name="name";
$db_table="table";
mysql_connect($db_host, $db_user, $db_pass) or die(mysql_error());
mysql_select_db($db_name) or die(mysql_error());
$query = mysql_query("SELECT * FROM tablename");
$result = mysql_query($query);
$num = mysql_num_rows($result);
for($count = 0; $count < $num; $count++)
{
//output the rows one by one(the actual images, not the URLs)
mysql_fetch_row($result);
echo("<br/>");
}
?>
I don't know if i should be using mysql_fetch_row in there..
I want my images to have some space in between; i was thinking the best way to accomplish that would be to add a "br" tag at the end of my loop so that every time a new image is displayed, a line break will be added to the end of the page.. Is that the best way to do it?
Thanks a bunch in advance!
To your first question, yes. To your second, also yes, if all your images are stored in the same directory. Mostly it's a matter of preference though.
Your for loop should look like this:
for($count = 0; $count < $num; $count++) {
$row = mysql_fetch_assoc($result);
echo "<img src='". htmlspecialchars($row["image"]) ."' alt='image' />";
}
br tags would probably be a bad idea. Set the images' display property to block in your CSS file. There are plenty of CSS manuals online.
With
$query = mysql_query("SELECT * FROM tablename");
$result = mysql_query($query);
$num = mysql_num_rows($result);
you do some things twice. You do not want $query to be the result of a mysql_query() call and then apply mysql_query() again.
In this case, the second call would happen with a resource object instead of a string - you got informed about it. By putting "" around, you turn it into a string again, but one which doesn't make sense to mysql.
To verify that, try to put or die(mysql_error()) to the problematic calls.
And to fix that, you can try
$query = "SELECT * FROM tablename";
$result = mysql_query($query) or die(mysql_error());
$num = mysql_num_rows($result);
BTW: you don't need $num when you replace the for loop with
while ($row = mysql_fetch_row($result))
// do stuff with $row
}
I've done a previous project based on image storage in a SQL database. the best way to store the images would be as a link, ie, '/stored_images/imagefilename.png'. When you need to reference the images just get the images into a while loop for each row in the table.
ie.
to get the images
<?php
$query = mysql_query("SELECT * FROM tablename");
while ($row = mysql_fetch_array($query)) {
echo '<img src="' . $row['column of url storage in SQL'] . '" />';
}
That will output all the images in the database, just change 'column of url storage in SQL' with the actual column name that you store in the SQL DB. also replace 'tablename' in the SQL query with the name of the table the images are being stored in.

correct way to upload image to database

i know some of you are going to say that this isnt the correct way but im on a tight deadline to finish an application and as of now i cant go back and modify the code to store the images in a directory.
now that thats cleared
the question i had is i inserted an image into the database by typing this.
(dont mind the class security call, all that is doing is a few checks if the data is valid)
$filename = $security->secure($_FILES['imgschool']['name']);
$tmpname = $security->secure($_FILES['imgschool']['tmp_name']);
$imgsize = $security->secure($_FILES['imgschool']['size']);
$imgtype = $security->secure($_FILES['imgschool']['type']);
$school = $security->secure($_POST['school']);
//begin upload
if($imgsize > 0) {
$handle = fopen($tmpname, "r");
$content = fread($handle, filesize($tmpname));
$content = addslashes($content);
//code to add all this to database
}
the variable $content is the image and all its getting is the addslashes. i remember someone once mentioning to do it with something called base64 but i can barely recall how it was written.
this is how i am calling the image from the database
aside from all the queries and whatnot
this is the main part that is calling the image
header("Content-length: ".$imgsize);
header("Content-type: ".$imgtype);
header("Content-Disposition: attachment; filename=".$imgname);
print $row['img'];
the problem i am having is that instead of the image showing. the url is only showing, so in this case i only see this
http://localhost/admin/school-catalog.php?page=gallery&id=4
when opening the page to view the image with the correct params set in the url.
for those that wanted to see the query that is being done to save the image and so forth
i copied the whole section
//save image to db
if(isset($_POST['btnupload'])) {
$filename = $security->secure($_FILES['imgschool']['name']);
$tmpname = $security->secure($_FILES['imgschool']['tmp_name']);
$imgsize = $security->secure($_FILES['imgschool']['size']);
$imgtype = $security->secure($_FILES['imgschool']['type']);
$school = $security->secure($_POST['school']);
//begin upload
if($imgsize > 0) {
$handle = fopen($tmpname, "r");
$content = fread($handle, filesize($tmpname));
$content = base64_encode($content);
}
$save = mysql_query("insert into tbl_schoolgallery(id,hash,img,imgtype,imgsize) values(null,'$school','$content','$imgtype','$imgsize')") or die(mysql_error());
header("Location: school-catalog.php?page=school_gallery");
}
//call image from db
$query = mysql_query("select * from $tbl where id = '$id'") or die(mysql_error());
while($row = mysql_fetch_assoc($query)) {
$imgtypeget = explode("/", $row['imgtype']);
$imgname = "img.".$imgtypeget[1];
$imgtype = $row['imgtype'];
$imgsize = $row['imgsize'];
header("Content-length: ".$imgsize);
header("Content-type: ".$imgtype);
print base64_decode($row['img']);
print $row['img'];
}
Using addslashes is extremely incorrect. Depending on whether your column is a TEXT field or a BLOB field, you should use Base64 or mysql_real_escape_string.
Using Base64 isn't that hard; you may as well use that way. Just replace addslashes with base64_encode and echo the image with base64_decode.
There's a bit easier way to write the whole thing, for that matter:
// begin upload
if ($imgsize > 0)
{
$content = file_get_content($tmpname);
$content = base64_encode($content);
}
And then to output you really only need to do
header("Content-type: ".$imgtype);
echo base64_decode($img);
If the column is a BLOB, however, you can directly use mysql_real_escape_string:
// begin upload
if ($imgsize > 0)
{
$content = file_get_content($tmpname);
$content = mysql_real_escape_string($content);
}
And then:
header("Content-type: ".$imgtype);
echo $img;
Although judging from your current symptoms, I'm guessing you also have a bug relating to how your image is being stored and recalled from the database, and I'd need to see that part of the code where you make the queries to insert and read from the database before I could help you fix that part.
Your current code seems mostly fine. A few issues:
print base64_decode($row['img']);
print $row['img'];
You probably meant to get rid of the second row. Also, you should use echo instead of print; everyone uses it, it can be slighty faster sometimes, and print doesn't really have any benefit other than returning a value:
echo base64_decode($row['img']);
$security->secure() appears to be some sort of sanitization function. Just use mysql_real_escape_string() - that's the one you're supposed to use. Except $imgsize; you might want to use intval() on that one since you know it's supposed to be an integer.
Also here:
$query = mysql_query("select * from $tbl where id = '$id'") or die(mysql_error());
You name the table tbl_schoolgallery a few rows above that. I assume $tbl == 'tbl_schoolgallery', but for consistency, you should either use $tbl in both places or tbl_schoolgallery in both places.
Also, replace that while with an if - your code would cause trouble if it ever loops more than once, anyway.

Categories