What happens to binary files in file_get_contents? - php

I'm trying to read a file in php and store it as a varbinary in sql server. The process works for text files, but I'm still having trouble with images.
I'm using the following lines to read the file contents into a string, but I'm not sure that that's not where my problem lies:
$data = NULL;
$validators = NULL;
if($file = file_save_upload('file', $validators, FALSE, 0)){
$data = file_get_contents($file->getFileUri());
$filename = $file->getFilename();
}
Then I pass the $data string to a prepared statement:
$conn = $this->_get_connection();
$sql = "
EXEC JC_Update_Document_SP
...
?,
...;
";
$file_input = [
[$data, NULL, NULL, SQLSRV_SQLTYPE_VARBINARY],
];
$stmt = sqlsrv_prepare($conn, $sql, $file_input);
if(sqlsrv_execute($stmt) === false){
die(print_r(sqlsrv_errors(), true));
}
where the $data field feeds into a varbinary column in a stored procedure in the database.
Another method I tried involved converting the $data varchar to a varbinary(max) field in the database, but either way, I get back a broken image.
So my question is this... is file_get_contents messing up my binary data? How would I read the image file and upload it to the database for later retrieval?

I found the bin2hex function. I'm still unclear on why this is needed, but it gets the job done.

Related

Download to root and after delete files from database

I have this function, and this deletes textfiles after a certain age from my database automatically.
$r = new textfiles;
$db = new DB;
$currTime_ori = $db->queryOneRow("SELECT NOW() as now");
...
if($this->site->textfilesretentiondays != 0)
{
echo "PostPrc : Deleting textfiles older than ".$this->site->textfilesretentiondays." days\n";
$result = $db->query(sprintf("select ID from textfiles where postdate < %s - interval %d day", $db->escapeString($currTime_ori["now"]), $this->site->textfilesretentiondays));
foreach ($result as $row)
$r->delete($row["ID"]);
}
Now I would edit this function so that at first all textfiles are automatically downloaded in a root directory /www/backup and then the script should delete the textfiles with the string $r->delete($row["ID"]);
At the moment I have no idea how I could implement this.
For me it's seems to be impossible to give you an completely answer to your question because leak of informations.
Do you store the whole file-content in database or only the path and filename?
It would help us to see whats the content of "$row" which represents one row from database.
If you just store the filename (and optionally the path) you could use the "copy" (http://php.net/manual/de/function.copy.php) function from php to copy the file to your backup-directory. Please note, you have to ensure that the user who's executing the script or running the web-server have the privileges to write into the directory.
You could add this functionality to class textfiles as as method like makeBackup.
There are few information, but I'll give it a try. If you want to backup the rows before deleting them, you can store them in .txt file in json_encoded form using this piece of code inserted in the FOREACH loop, before delete command:
$myfile = fopen("/www/backup/".$row["ID"].".txt", "w") or die("Unable to open file!");
$txt = json_encode($row);
fwrite($myfile, $txt);
fclose($myfile);
By your approach ..
function delete ($id){
$result = $db->query(sprintf("select * from textfiles where id=$id);
//if you have filepath use copy as SebTM suggested
$path = $row['path']; //assuming path is the column name in ur db
$filename = basename($path); //to get filename
$backup_location = '/www/backup/'.$filename;
copy($path, $backup_location);
//if you have data in db
$content = $row['data'] //assuming data to be backed up to file is in a field 'data'
$backup_location = '/www/backup/file.txt';
file_put_contents($backup_location, $content);
}
But this is not the most optimal approach , you could shift even the initial query into delete function above , and call delete function only once, instead of calling it in a loop ..

MySQL: How to store a file into a medium blob field binary with HEX

I have wrote a simple VFS (Virtual File System) in PHP (StreamWrapper) that puts it's data into a MySQL database. The field that stores the data is a medium blob.
Things you can do for example in PHP:
copy( 'mytext.txt', 'dbfs://mytext.txt' );
copy( 'mytext.pdf', 'dbfs://mytext.pdf' ); or visa versa/etc.
The problem is binary data such as a pdf to pass thru a SQL statement. Escaping, unquoting, base64 etc ruin the data or take too much memory (overhead), for example base64 takes 3x the space.
The best thing to do is, i think, is make it a hex string (only twice the space) that will be stored in the database as binary (no overhead). I have seen the HEX command of MySQL but can't get it to work like I want.
For example, the next statement does not store it as binary data into the blob:
UPDATE dbfs SET data=0xFF883838<very long string>FFA9999...... WHERE (fid=<number>)
The function I made:
private function writeFile( $fid, &$uData = null, $iFileSize = null )
{
$sSql = 'UPDATE '.self::$dbTableNameFat.
' SET data="'.(($uData !== null)?('0x'.bin2hex($uData)):null).'"'.
',size="'.((int)$iFileSize).'" WHERE ( fid="'.$fid.'" );';
return $this->writeQuery( $sSql );
}
The blob contains the data but in HEX format and not in binary. How can I achieve the behaviour I want?
Use a prepared query. I'll use PDO-style syntax.
private function writeFile($fid, &$uData = null, $iFileSize = null) {
$stmt = $this->prepare(
"UPDATE " . self::$dbTableNameFat .
" SET data = :data, size = :size WHERE fid = :fid");
$stmt->execute(array( 'data' => $uData,
'size' => $iFileSize,
'fid' => $fid
);
};
PDO documentation is here

get NULL to be saved to file

I have a table that I am trying to save to an sql file using php.
The table has fields with NULL.
However when I try and loop through the table rows to save to file, the NULLs become blank strings, is there anything I can do to prevent this?
Below is a snippet of the code
$sql="SELECT * FROM myTable";
$sql_result=mysql_query($sql);
while ($row = mysql_fetch_array($sql_result,MYSQL_ASSOC)){
$saveSql.=$row['myId'].",";
$saveSql.="'".$row['myName']."',";
$saveSql.=$row['myAge'].",";
}
$handle = fopen('database.sql', 'w');
fwrite($handle,$saveSql);
If there are NULL values, then they are not saved to file, they are saved as empty strings.
PHP stringifies null as "" (empty string).
If you want to save to file while keeping fidelity use a serializer like seralize or json_encode.
Writing:
fwrite($handle, serialize($saveSql));
Reading
$import = unserialize(fread($handle));
People forget the power of if statements....
if ($row['myId'] == "") { $saveSql .= "NULL"; }
Etc...
That's to be expected. An SQL null is mapped to a PHP null, which gets converted to an empty string when you output it. If you want the literal letters n, u, l, l, to be output, then you'll have to do that conversion yourself, e.g.
$text = isnull($row['myName']) ?: 'NULL';
try this
$sql="SELECT * FROM myTable";
$sql_result=mysql_query($sql);
while ($row = mysql_fetch_array($sql_result,MYSQL_ASSOC)){
if(isNull($row['myId']){$saveSql.="NULL".",";}else{$saveSql.=$row['myId'].",";}
if(isNull($row['myName']){$saveSql.="NULL".",";}else{$saveSql.=$row['myName'].",";}
if(isNull($row['myAge']){$saveSql.="NULL".",";}else{$saveSql.=$row['myAge'].",";}
}
$handle = fopen('database.sql', 'w');
fwrite($handle,$saveSql);

Download image from blob field to hard disk using php

I have a mysql blob field in which our team stored an image for every record. Now I want to download all images on my hard disk through php script. A prompt response will be appreciated.
Best Regards...
Aisha
$result=mysql_query("SELECT * FROM test WHERE 1");
while($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
$filename = rand(1, 100).'.txt';
file_put_contents('./'.$filename, $row['blob']);
}
This is working (tested).
It wil save the file under a random filename (1-100.txt).
You can change the filename by changing $filename.
And here is a simple sample MySQL-table with 2 demo files with content Test #1 and Test #2:
CREATE TABLE IF NOT EXISTS `test` (`blob` blob NOT NULL) ENGINE=InnoDB DEFAULT CHARSET=latin1;
INSERT INTO `test` (`blob`) VALUES(0x5468697320697320746573742023312e), (0x5468697320697320546573742023322e);
you can use file_put_contents,
fetch rows from your database and foreach row write blob/data to file
Error in Writing to Image file from PHP
http://php.net/manual/en/function.file-put-contents.php
You can try this also........
function save_file($file_id, $target_folder) {
$result = $DB->get_file($file_id);
$file_content = $result->fields['your_file_content_field'];
$name = $result->fields['name'];
/* Decode only if the file contents base64 encoded
* before inserting to database.
*/
$file_content = base64_decode($file_content);
return file_put_contents($target_folder.'/'.$name, $file_content);
}

Insert image binary from xml data to mysql in PHP

I have some photos (not big, only 8kb) in mysql database (in my desktop). the field type is blob. i want to export the table to xml file then upload it to my database website. but it not success. Here is what i have done :
Exporting the data to xml (in my computer desktop):
FileStream fs = new FileStream(filename,FileMode.Create,FileAccess.Write,FileShare.None);
StreamWriter sw = new StreamWriter(fs,Encoding.ASCII);
ds.WriteXml(sw); //write the xml from the dataset ds
Then upload the xml from my joomla website. i load the xml before insert it to the database
...
$obj = simplexml_load($filename);
$cnt = count($obj->mydata); //mydata is the table name in the xml tag
for($i=0;$i<cnt;$i++)
{
...
$myphoto = 'NULL';
if(!empty($obj->mydata[$i]->myphoto))
{
$myphoto = base64_code($obj->mydata[$i]->myphoto);
}
//insert to the database
$sqlinsert = "insert into jos_myphoto (id,myphoto) values(".$i.",".$myphoto.")";
...
}
...
it keep telling me 'DB function failed'. when value of $myphoto is null, the query work well but if $myphoto is not null, the error appears. i think there is something wrong with the code
$myphoto = base64_code($obj->mydata[$i]->myphoto).
i try to remove base64_code function but it dont work. How to solve this problem? Sorry for my bad english
Your data may contain which needs escaping put mysql_real_escape_string() function and try
It is always a good habit to store data using this function which save you from sql injection also.
And put quotes around the column data.
$sqlinsert = "insert into jos_myphoto (id,myphoto)
values(".$i.",'".mysql_real_eascape_string($myphoto)."')";

Categories