I want to save (insert) a uploaded file to a database with PHP, which the type of the database filed is varbinary.
Finally I want to have the content of VarBinary (output) like when file is read in C# and then is stored in byte array and array is inserted to VarBinary.
Also my connection to the database is with sqlsrv.
The type of my files are just PDF and images.
I try this code but my output is different with the output of C#:
$handle=#fopen($_FILES["my_file"]["tmp_name"], 'rb');
$content= file_get_contents($_FILES["my_file"]["tmp_name"]);
$content = unpack("N*",$content);
$content= implode($content);
$sql = "INSERT INTO files (file_data) VALUES (CONVERT(varbinary(MAX)?)";
$params=array();
array_push($params,$content);
$table=sqlsrv_query( $conn, $sql, $params);
"$conn" is the name of my connection that works correctly.
PHP doesn't have a "byte array" data type. What it has is a string type, which is a byte array for all intents and purposes. To read the binary content of a file into a variable which is as close to a byte array as you'll ever get in PHP, do:
$content = file_get_contents($_FILES['my_file']['tmp_name']);
Yup, that's it. Nothing more to do.
I'm not particular familiar with the sqlsrv API, but perusing its documentation it appears that you can (need to?) set a flag this way to flag the data as being binary:
sqlsrv_query($conn, 'INSERT INTO files (file_data) VALUES (?)', array(
array($content, SQLSRV_PARAM_IN, SQLSRV_PHPTYPE_STRING, SQLSRV_SQLTYPE_BINARY)
));
I propose to always convert your binary data to base64.
So it can be stored in database easily and also it can be transfered from somewhere to anywhere with minimum headache!
$handle=#fopen($_FILES["my_file"]["tmp_name"], 'rb');
$elephantContent = file_get_contents($_FILES["my_file"]["tmp_name"]);
$rabbitContent = base64_encode($elephantContent);
//Now ...
$sql = "INSERT INTO files (file_data) VALUES (?)";
sqlsrv_query($conn , $sql , array($rabbitContent) );
file_data field in files table can be varchar, varbinary, blob, text ! :)
Now it can be invoked from database and be packed into a img tag directly.
<img src="data:image/jpeg;base64,PUT `file_data` CONTENTS HERE!" alt="..." />
You can store file type and alt properties in database and put them in tag.
You even can convert it to binary in database (if you insist on seeing binary data in db) (mysql 5.6+)
SELECT FROM_BASE64(`file_data`) as elephant_content from `files` WHERE ...
... And I'm pretty sure that there is equivalent method to do it so in SQL.
For example read this:
https://social.technet.microsoft.com/wiki/contents/articles/36388.transact-sql-convert-varbinary-to-base64-string-and-vice-versa.aspx
Related
I get the error message SQLite3::exec(): unrecognized token: "'Date" when I insert a command into a SQLite database.
If I have the SQL commands echoed and execute them via the console, this also works. The data for this comes from a dbase database.
If I enter a string for fieldname the insert commands will work.
$field=unpack( "a11fieldname/A1fieldtype/Voffset/Cfieldlen/Cfielddec", substr($buf,0,18));
$db = new SQLite3('databases/test.db');
$sqlCode .= "INSERT INTO HEADER (name) VALUES ('".$field['fieldname']."');";
$db-> exec($sqlCode);
Would be that much easy to use prepare satement against sql injections
If I enter a string for fieldname the insert commands will work
make sure if fieldname is a text value
I am using pdo :
$sqlCode = "INSERT INTO header VALUES (:name)";
$query = $db->prepare($sqlCode);
$query->bindValue(':name', $field['fieldname'], SQLITE3_TEXT);
$result = $query->execute();
EDIT : Error says unrecognized token Date, So, if fieldname is a date you might need to change SQLITE3_TEXT to SQLITE3_BLOB OR SQLITE3_INTEGER Usualy not needed.
But you need to insert date into date column not into name column
EDIT 2 :
it's a bit complicated.
See here for a full description of the dbf file format.
So it would be best if you could use a library to read and write the dbf files.
If you really need to do this yourself, here are the most important parts:
Dbf is a binary file format, so you have to read and write it as binary. For example the number of records is stored in a 32 bit integer, which can contain zero bytes.
You can't use string functions on that binary data. For example strlen() will scan the data up to the first null byte, which is present in that 32 bit integer, and will return the wrong value.
If you split the file (the records), you'll have to adjust the record count in the header.
When splitting the records keep in mind that each record is preceded by an extra byte, a space 0x20 if the record is not deleted, an asterisk 0x2A if the record is deleted. (for example, if you have 4 fields of 10 bytes, the length of each record will be 41) - that value is also available in the header: bytes 10-11 - 16-bit number - Number of bytes in the record. (Least significant byte first)
The file could end with the end-of-file marker 0x1A, so you'll have to check for that as well.
See asked : binary safe write on file with php to create a DBF file
Final Word : you need DBF library
Data File Header Structure
How can I insert a icon in my database from php through object oriented method ?
table name
ser_icon is my database column name
You must mention what have you done so far to fix the issue. Any solution/codes you can mention. But here is a small help:
Its not recommended to store any kind of image into the database. Rather store it in directories and save the paths into the db for manipulation. However, if you still want to save any image in the db, you need a field with type 'BLOB', which is used to save images/icons in the database.
You can do something like this:
// Image submitted by form. Open it for reading (mode "r")
$fp = fopen($_FILES['file_name']['tmp_name'], "r");
if ($fp) {
$content = fread($fp, $_FILES['file_name']['size']);
fclose($fp);
// Add slashes to the content so that it will escape special characters.
// As pointed out, mysql_real_escape_string can be used here as well. Your choice.
$content = addslashes($content);
// Insert into the table "your_table_name" for column "ser_icon" with our binary string of data ("content")
mysql_query("Insert into your_table_name (ser_icon) Values('$content')");
}
I have a table for things properties.
Such as id, amount, owner, attributes.
The attributes is stores as blob, and could be any small information about the thing itself,.
Like, the thing may have text on it, or it may has something about it that makes it more unique.
When you export a table/row in PhpMyAdmin, I get these really nice values
INSERT INTO `user_things` (`owner_id`, `id`, `thingId`, `count`, `attributes`) VALUES
(1, 6, 101, 1, 0x10c8431200);
And what I'm trying to do, is being able get information from the blob in PHP that displays the blob the same way PhpMyAdmin displayed it, so I can with PHP build a string of query there the blob value stays at a 0x00000 value.
I've tried to use this code: (mysqlQuery is a simplified function I created for mysqli queries, and that one works perfect so don't worry about that part)
$thing = mysqlQuery("SELECT * FROM `user_things` LIMIT 1;");
$blob = $thing["attributes"];
but it doesn't work very well, and I've tried base64_encode and that doesn't give me the 0x000 either.
I would highly appreciate any help on this, how I can get the blob to the same type of value that PhpMyAdmin displays it as.
0x is just a convention for expressing hexadecimal values.
The 0x10c8431200 hexadecimal value is the same like 72079315456 decimal value.
You can try to convert binary data to hex with the bin2hex function.
Example:
$thing = mysqlQuery("SELECT * FROM `user_things` LIMIT 1;");
$blob = $thing["attributes"];
echo bin2hex($blog);
I am building a function that is inserting complex data into a MySQL table to be used as a queue for a CSV file creation. Without going into explicit details, what I want is simply to convert an array into serialized format using json_encode, insert it to a MySQL table with a prepared statement, and then retrieve that data, json_decode, and have the original data in the exact same form it was prior to insertion.
The code as it stands looks something like this:
// Array data previously created
foreach ( $array as $key => $element ) {
$array[$key] = htmlspecialchars($element,ENT_QUOTES);
}
$this->db->query("UPDATE `table` SET `blob_field` = '".$this->db->escape($array)."' WHERE `id` = '".(int)$id."'");
Then I retrieve the data using:
$decoded_array = $this->db->query("SELECT `blob_field` FROM `table` WHERE `id` = '".(int)$id."'")->row['blob_field'];
$decoded_array = json_decode($decoded_array);
$decoded_array = array_map('htmlspecialchars_decode',$decoded_array);
// Add to CSV using fputcsv standard process
The resulting CSV is about 99.9% perfect. But when opened in Excel about 0.1% of the rows have columns that are jumping where they should not. Furthermore, every instance of \r\n appears to be getting replaced with the Windows newline character.
My question is... what am I doing wrong? Why are the newline characters being replaced with the Windows equivalent, and why does the CSV look messed up when opened in Excel?
I recently switched from MySQL to PostgreSQL. I have one problem left however.
Previously, I would store small images in the BLOB format in MySQL.
PostgreSQL doesn't know such thing as a BLOB.
I tried using BYTEA field type instead. This actually inserts an large (hexadecimal?) string I guess, but now I'm stuck trying to get this string back to displaying an actual image in PHP..
Any ideas? Thanks in advance.
Here is a piece of code I use to save the image in the database:
$data = bin2hex(file_get_contents('php://input'));
if (!empty($data)) {
$sql = "UPDATE asset SET data = X'%s' WHERE uuid = '%s'";
$args = array($data, $asset_uuid);
}
psql (9.1.3) and php 5.3.6 are used
Bytea is a byte array. It's not a bit pattern. See section 4.2.1.5 of PostgreSQL Lexical Structure.
The correct way to enter bytea is '\x...' with hex values. So what you want is SET data = '\x%s'.
You might also want to look into prepared statements with pg_prepare.
Edit: I was able to insert a (text) file into a bytea with this:
$source = file_get_contents( 'hello.php' );
$insert = pg_prepare( $conn, '', 'insert into t (name, data) values($1,$2)' );
pg_execute( $conn, '', array( 'hello.php', $source ) );
3rd Edit: This works fine to insert the file into the database. However, the pgsql driver in PHP is quite impolite. The only way to retrieve the actual data back is using the old bytea escape mechanism, as detailed here: pg_unescape_bytea.
pg_query('SET bytea_output = "escape";');
$result = pg_query( 'select data from t' );
while ( $row = pg_fetch_row( $result ) ) {
echo pg_unescape_bytea( $row[0] );
}
I'm sorry about how annoying this is. The PostgreSQL interface in PHP can do with some major overhaul for binary values.
To insert bytea contents with the pg_* API, the binary value should always be run through the pg_escape_bytea() function, even if it's passed to the pg_execute or pg_query_params functions.
This is because the pg_* layer doesn't "know" that a particular parameter has binary contents, and it does not implement any real support for parameter types anyway. So the text representation must be used. It can either be in the escape form or the hex form, it doesn't matter to the PG server, and it's independant of the value of bytea_output, which is meaningful only for values read from the server.
Example:
$esc=pg_escape_bytea("\000\001\002");
pg_query_params('INSERT INTO some_table(some_col) VALUES($1)', array($esc));
To read bytea contents with the pg_* API, the value must be run through pg_unescape_bytea() after the fetch. Assuming the client library is not older than 9.0 (libq.so.5.3 or higher), it can decode the contents whether it's in hex form or escape form and it will autodetect it. Only with an older library would it be necessary to force bytea_output to escape for it to decode properly, either dynamically with SET or statically for the whole database (ALTER DATABASE SET bytea_output=escape) or in postgresql.conf for the whole instance.
Example:
$p=pg_query("SELECT some_col FROM some_table WHERE...");
$r=pg_fetch_array($p);
$contents = pg_unescape_bytea($r[0]);
Both answers posted here gave me some thoughts, but none were 100% of the answer.
So, I will explain in this answer what I did to get it to work.
When displaying the image, I used this:
header('Content-Type: image/jpeg');
$data = pack("H*", pg_unescape_bytea($data));
echo $data;
I'm running PHP 5.3.8, in PHP 5.4.0 it turns out you can use hex2bin instead of pack.
When adding the image to the database, I used this:
$data = pg_escape_bytea($data); // Escape input for PostgreSQL
$sql = "UPDATE asset SET data = '%s'WHERE uuid = '%s'";
I'm glad it is working now. Thank you both Daniel and Johann!