Write string with null bytes inside (PNG image) into MySQL in PHP - php

How do I write and read string (~200 KB) with lots of 0 bytes inside into MySQL BLOB field?
This is not working:
$data = ... // PNG image raw data
$queryPart = "'" . addslashes($data) . "'";
... compose and execute query

The proper way to escape input data when using the legacy MySQL library is mysql_real_escape_string().

Even if they "can", databases are not made to stock binary files. It's more efficient to have in your table the path of the files on your server.

Use mysql_real_escape_string(), as it makes a call to the MySQL library to clean the given data.
http://php.net/manual/en/function.mysql-real-escape-string.php

Related

Undesired data truncation when updating a MEDIUMBLOB

I'm trying to write in a BLOB in my MariaDB using a PHP post call. This BLOB comes from getting a BASE64 from a canvas:
var data= $('#signatureDiv').signature('toDataURL');
var base64data= data.replace(/^data:image\/(png|jpg);base64,/, "");
$.post("myFunc.php", {imgContents: base64data}, function(data) {});
Now, in myFunc.php:
$imgContents = $_POST['imgContents'];
$decodedPNG = base64_decode($imgContents);
$defTest = "UPDATE recogidas SET FirmaProv = ':blobFirma' WHERE ID=$index";
$preparedpdo = $mypdoObject->prepare($defTest);
$preparedpdo->bindParam(':blobFirma', $decodedPNG, PDO::PARAM_LOB);
$preparedpdo->execute();
echo $decodedPNG;
I decode the PNG to save it as a BLOB. Then I prepare a SQL update to upload this BLOB to a proper MEDIUMBLOB column. However, the data is always truncated to few bytes!! Exactly to those bytes:
3A626C6F624669726D61
When it, as a PNG, needs around 100Kb. I tried using this at the beggining of the PHP:
ini_set("odbc.defaultlrl", "1000K");
But it has no effect. To make sure the decode was right, I tried to echo the decoded BLOB, and it returns if correctly.
Why is my database truncating the data to a pack of bytes?
Extra information: It doesn't matter how the picture I make in the canvas is, the data uploaded to the data base is always those same characters.
Why is my database truncating the data to a pack of bytes?
It isn’t. If you had bothered to check what those hex bytes 3A626C6F624669726D61 actually mean, you would have seen that it is :blobFirma. And since you instructed the database to store that string value in your statement, this is absolutely the result that is to be expected.
If you don’t want to store a fixed string value into the column - then remove the quotes around the placeholder from the statement …

How to save BLOB to SQL-Server using PHP

I'm able to upload an image file and using PHP's file_get_contents put the binary into memory. From there I've attempted to use a basic update or insert query statement to then put that data into a blob. It keeps throwing errors.
In addition I've tried to use the addslashes PHP function as well, and it still doesn't work.
I've tried:
if (is_uploaded_file($_FILES['myFile']['tmp_name'])){
$fileData = file_get_contents($_FILES['myFile']['tmp_name']);
$fileData = unpack("H*hex",$fileData);
$content = "0x" . $fileData['hex'];
}
Then I try to insert into my database and it doesn't work either.
The datatype for my BLOB field is image.
The error I am most often getting is:
mssql_query(): message: Operand type clash: text is incompatible with image (severity 16)
Any help would be appreciated!

Pulling BLOB image data from MySQL in PHP

I was reading from a few tutorials on how to upload my image into the DB as binary opposed to putting them on the server itself, well I got it to work like this:
PHP:
$image = chunk_split(base64_encode(file_get_contents($tmpfile)));
mysql_query("INSERT INTO images (`img_location`, `caption`, `user`, `genre`, `when`) VALUES ('$image', '$caption', '$id', '$genre', '$when')");
My issue is how do you now pull it from the database, I've read several ways of doing it, tried them all, can't figure it out, I'm not getting a MySQL error, here's how I'm trying it:
$get_pics = mysql_query("SELECT * FROM images WHERE user='$id' ");
while($get_pics2 = mysql_fetch_array($get_pics))
{
$sixfour_enc = base64_decode($get_pics2['img_location']);
$new .= "<img src=\"".$sixfour_enc."\" >";
}
This works... kind of, what's happening is that it's printing out raw binary in the IMG tag.
How do I get this to compile to a readble image again? Also, is storing the images in the database stupid? Should I just do what I usually do and store them on the server?
Thank you
-mike
You can store images in your database if you want to (though there's nothing wrong with just storing them as files either, choose whatever is appropriate in your situation), but store the raw binary data in a BLOB (i.e. don't encode it with base64). You can embed the binary data you get from file_get_contents in your query directly, provided you use the proper escape function (mysql_real_escape_string in your case) first.
As for the outputting of the image, you can do it the way you're doing it right now, but you'll have to output it base64-encoded and with a data URI scheme like this:
echo '<img alt="embedded image" src="data:image/png;base64,' . chunk_split(base64_encode($get_pics2['img_location'])) . '">';
Note that there are some advantages and disadvantages of embedded image data. Some important disadvantages to be aware of are the severe overhead of base64 encoding (around 33% larger than original) and potential caching problems.
If you don't have any particular reason to store image data in your database then I strongly advise that you just do it the normal way.
This is because, your database engine will be taking a significant performance hit since you will be getting and putting more data than necessary.
Furthermore, BLOB fields on MySQL tables are significantly larger than other tables in terms of size and perform slower on most scenarios.
Just imagining the overhead on your server once you implement this gives me the chills. ;)
I guess it all boils down to scalability. Once your database fills up, your server become less responsive and will eventually become a real hog. Your next options would be to increase server RAM or revise your code to accommodate the bigger load.
Just my 2 cents, hope this helps!
Good luck!
Actually, the best aproach is to have a PHP script to output the binary of the image with proper headers (say getimage.php) and the script used to generate the HTML will have a code like this:
$get_pics = mysql_query("SELECT id FROM images WHERE user='$userid' ");
while($imglist = mysql_fetch_array($get_pics))
{
$new .= '<img src="getimage.php?id='.$imglist['id'].'" title="'.$imglist['caption'].'" />';
}
So the HTML will look like:
<img src="getimage.php?id=12345" title="the caption of" />
You must have a primary key (why not already?) on the table images, let's say id.
The "getimage.php" script shall extract the binary and output the content (assuming that the field img_location contains the actually content of the image:
<?php
// this will output the RAW content of an image with proper headers
$id=(int)$_GET['id'];
$get_img = #mysql_fetch_assoc(#mysql_query("SELECT img_location FROM images WHERE id='$id' "));
$image = imagecreatefromstring(base64_decode($get_img['img_location']));
if ($image){
//you may apply here any transformations on the $image resource
header("Content-Type: image/jpeg"); //OR gif, png, whatever
imagejpeg($image,null,75); //OR imagegif, imagepng, whatever, see PHP doc.
imagedestroy($image); //dump the resource from memory
}
exit();
#mysql_close();
?>
This approach will give you flexibility.
However, you may need to check and sanitize the variables and choose another method of connection to MySQL, as MYSQLi or PDO.
Another good idea is the use of prepared statements to prevent SQL injections.

In PHP (plphp), how can we manage a file stored in a bytea with Imagick?

We are storing entire image files in PostgreSQL, using bytea columns.
In PHP, am trying to open an image file from the bytea field (these stored as hex), then want to manipulate/convert the image using Imagick.
Must the bytestream be converted out of hex to be manageable - in a file-like way - by Imagick? Is there any other secret sauce?
I wouldn't be surprised if we had to read beyond the file header bits, either. Offending snippet is below:
// Decode image from hex?
$image = new Imagick ($row['thewholefile']);
// ERROR: Uncaught exception 'ImagickException' with message 'Unable to read the file: /x0000000 (etc)
Actually the problem here had to do with PostgreSQL's bytea presentation format- as we are using v9.n of PG, the default output is hex:
We had to first set output to PG's 'Old School' bytea handling. Then, by pg-unescaping the raw column data, we had something we could work with:
SET bytea_output = 'escape'
$unescaped = pg_unescape_bytea($content);
You need readimageblob. Here you go:
http://www.php.net/manual/en/function.imagick-readimageblob.php
The error is pretty clear, just as the documentation: the constructor requires a filename or an array of filenames. Use Jauzsika's solution.

How can i restore or access MySQL Blob field into jpeg in PHP

How can i restore or access MySQL blob field so I can preview it as HTML using PHP codes? Is there an available function in PHP so I can store as jpeg those blob field.
Storing is easy. Assuming you have a mysql table with BLOB field for pictures....
Once the image is uploaded you get the contents of the file into memory and then insert into the blob field.
<?php
$file = '/tmp/MyImg.jpg';
// you migh want to escape it just in case
$data = file_get_contents($file);
// Insert into database
$sql = "INSERT INTO my_picture_table (`picture_blob_field`) VALUES ('$data');"
?>
Retrieving is fairly simple as well. It is simpler to make a separate file to load images from blob.
<?php
// file = getPicture.php
$id = (int) $_GET['id'];
$sql = "SELECT `picture_blob_field` FROM `my_picture_table` WHERE `id` = $id"
// query the db
// store data into var $picData
// Set the content type and print the data.
header("Content-type: img/jpeg");
echo $picData;
?>
This is all you have to do... Now in HTML page just create an
<img scr="getPicture.php?id=PICTURE_ID alt="blah blah" />
Note that above example is for JPEG type, store the file type in the db and then use it to specify file type with header("Content-type: img/xxx")
Hope this solved your problem.
I found an example/tutorial on storing images in mysql. If above is not clear look through the code (its paginated, so look at the other pages)
The code presented above is vulnerable to SQL injection attacks and will in any case fail at the first byte of the JPEG that happens to match the ASCII code for a quote mark (which should happen quite quickly). I do see your comment that you "might" want to escape the data, but it should be emphasized that in a big binary file, there will almost certainly be a byte that matches the quote mark. It's not "just in case," it's practically every case.
Use mysql_real_escape_string() on the JPEG data and the id parameter (which comes from the user, who may be malicious). Better yet, use PDO and parameter substitution to avoid that mess.
Also, the content type must be image/jpeg, not img/jpeg.

Categories