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 …
Related
I am trying to write an image into an SQL Server database in binary format with no success. The image uploaded from my frontend (AngularJS) to my server (PHP) is a Base64 string and I need to then convert it to a raw binary file starting with 0x as the database requires a varBinary(max) datatype.
Everything I try seems to end up with the value wrapped in single quotes thus trying to parse it as a varchar and resulting in an error:
General error: 20018 Implicit conversion from data type varchar(max) to varbinary(max) is not allowed.
My current code snippet:
$img = (binary) '0x'.strtoupper(bin2hex($photo['PhotoImage']));
Seems to always result with single quotes and I don't know how to get around it:
PhotoImage='0x6956424F5277304B47676F414141414E53556845556741414156414141414651434141414141444D67336B464'
Update
After some playing around, I have located my problem, I just don't know how to resolve it.
This statement:
$img = (binary)('0x' . bin2hex($photo['PhotoImage']));
dd(gettype($img));
Which (to me) should be returning me a binary value, is in fact STILL returning a string and hence why my S-PROC is failing:
...
"<span class=sf-dump-str title="6 characters">string</span>"
</pre><script>Sfdump("sf-dump-1548954697")</script>
...
Also, as a small test, it seems PHP cannot declare a true binary:
$img = 5;
dd(gettype($img));
/* "<span class=sf-dump-str title="6 characters">integer</span>" */
$img = (binary)5;
dd(gettype($img));
/* "<span class=sf-dump-str title="6 characters">string</span>" */
How can I force PHP to convert this value to a true binary?
I was surprised that I was unable to find a straightforward answer to this question by searching.
I have a web application in PHP that takes user input. Due to the nature of the application, users may often use extended ASCII characters (a.k.a. "ALT codes").
My specific issue at the moment is with ALT code 26, which is a right arrow (→). This will be accompanied with other text to be stored in the same field (for example, 'this→that').
My column type is NVARCHAR.
Here's what I've tried:
I've tried doing no conversions and just inserting the value as normal, but the value gets stored as thisâ??that.
I've tried converting the value to UCS-2 in PHP using iconv('UTF-8', 'UCS-2', $value), but I get an error saying Unclosed quotation mark after the character string 't'.. The query ends up looking like this: UPDATE myTable SET myColumn = 'this�!that'.
I've tried doing the above conversion and then adding an N before the quoted value, but I get the same error message. The query looks like this: UPDATE myTable SET myColumn = N'this�!that'.
I've tried removing the UCS-2 conversion and just adding the N before the quoted value, and the query works again, but the value is stored as thisâ that.
I've tried using utf8_decode($value) in PHP, but then the arrow is just replaced with a question mark.
So can anyone answer the (seemingly simple) question of, how can I store this value in my database and then retrieve it as it was originally typed?
I'm using PHP 5.5 and MSSQL 2012. If any question of driver/OS version comes into play, it's a Linux server connecting via FreeTDS. There is no possibility of changing this.
You might try base64 encoding the input, this is fairly trivial to handle with PHP's base64_encode() and base64_decode() and it should handle what ever your users throw at it.
(edit: You can apparently also do the base64 encoding on the SQL Server side. This doesn't seem like something it should be responsible for imho, but it's an option.)
It seems like your freetds.conf is wrong. You need a TDS protocol version >= 7.0 to support unicode. See this for more details.
Edit your freetds.conf:
[global]
# TDS protocol version
tds version = 7.4
client charset = UTF-8
Also make sure to configure PHP correct:
ini_set('mssql.charset', 'UTF-8');
The accepted answer seems to do the job; yes you can encode it to base64 and then decode it back again, but then all the applications that use that remote database, should change and support the fields to be base64 encoded. My thought is that if there is a remote MS SQL Server database, there could be an other application (or applications) that may use it, so that application have to also be changed to support both plain and base64 encoding. And you'll have to also handle both plain text and base64 converted text.
I searched a little bit and I found how to send UNICODE text to the MS SQL Server using MS SQL commands and PHP to convert the UNICODE bytes to HEX numbers.
If you go at the PHP documentation for the mssql_fetch_array (http://php.net/manual/ru/function.mssql-fetch-array.php#80076), you'll see at the comments a pretty good solution that converts the text to UNICODE HEX values and then sends that HEX data directly to MS SQL Server like this:
Convert Unicode Text to HEX Data
// sending data to database
$utf8 = 'Δοκιμή με unicode → Test with Unicode'; // some Greek text for example
$ucs2 = iconv('UTF-8', 'UCS-2LE', $utf8);
// converting UCS-2 string into "binary" hexadecimal form
$arr = unpack('H*hex', $ucs2);
$hex = "0x{$arr['hex']}";
// IMPORTANT!
// please note that value must be passed without apostrophes
// it should be "... values(0x0123456789ABCEF) ...", not "... values('0x0123456789ABCEF') ..."
mssql_query("INSERT INTO mytable (myfield) VALUES ({$hex})", $link);
Now all the text actually is stored to the NVARCHAR database field correctly as UNICODE, and that's all you have to do in order to send and store it as plain text and not encoded.
To retrieve that text, you need to ask MS SQL Server to send back UNICODE encoded text like this:
Retrieving Unicode Text from MS SQL Server
// retrieving data from database
// IMPORTANT!
// please note that "varbinary" expects number of bytes
// in this example it must be 200 (bytes), while size of field is 100 (UCS-2 chars)
// myfield is of 50 length, so I set VARBINARY to 100
$result = mssql_query("SELECT CONVERT(VARBINARY(100), myfield) AS myfield FROM mytable", $link);
while (($row = mssql_fetch_array($result, MSSQL_BOTH)))
{
// we get data in UCS-2
// I use UTF-8 in my project, so I encode it back
echo '1. '.iconv('UCS-2LE', 'UTF-8', $row['myfield'])).PHP_EOL;
// or you can even use mb_convert_encoding to convert from UCS-2LE to UTF-8
echo '2. '.mb_convert_encoding($row['myfield'], 'UTF-8', 'UCS-2LE').PHP_EOL;
}
The MS SQL Table with the UNICODE Data after the INSERT
The output result using a PHP page to display the values
I'm not sure if you can reach my test page here, but you can try to see the live results:
http://dbg.deve.wiznet.gr/php56/mssql/test1.php
I've been trying to store images in mysql database by encoding them in a base64 string then passing them to a php script that in turn stores this string in a blob (I also tried text) filed. What happens is the string is sent to the php script as it is, but when stored in the database, its is stored as a completely different string.
Here is how i do it:
Bitmap image = BitmapFactory.decodeFile("/sdcard/photo2.jpg");
ByteArrayOutputStream stream = new ByteArrayOutputStream();
image.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteImage = stream.toByteArray();
String s = Base64.encodeToString(byteImage, Base64.NO_WRAP | Base64.URL_SAFE);
And then the string 's' is passed to the php script (correctly as I've checked it) and the script in turn insert it in the database.
This link http://diffchecker.com/kKD4w16C contains how the original encoded string (on the left of the screen) and the string that is stored in the database (on the right of the screen).
Any ideas why this is happening and how to prevent it?
Thanks in advance.
You dont notice, that u just cut on ~20% of string? Seems like there is limit for your DB field. Something like varchar(255) and u try to store 1500 length string.
http://tinyurl.com/c2e7hru - see here. I just copy the end of your DB field value and find it in "original" value.
Also, check your encoding.
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 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.