I'm having a problem with PHP and my SQL Server.
When I try to save a file into the database as a varbinary(MAX) type, it works perfectly, but when I try to save a file of 180k or more in the result, I only get part of the image:
$handle = #fopen($fileTmpName, 'rb');
if ($handle)
{
$content = #fread($handle, filesize($fileTmpName));
$content = bin2hex($content);
#fclose($handle);
}
$select = mssql_query("EXEC [DB_Name].[dbo].[Table_Name] #Data = ".$content."");
$result = mssql_fetch_array($select);
$_SESSION['fileContent'] = $result['Data'];
<img src="../applications/framework/images.php" />
image.php file contains the following:
header("Content-type: ".$fileType);
header("Content-Length: ".$fileSize);
header("Content-Disposition: inline; filename=".$fileName);
echo $_SESSION['fileContent'];
As a result, I only get part of the image.
I mean that it only loads the first part of the real image. It seems that it inserts only the first part of the content into the database instead of all of it.
How can this be solved?
check the table structure. It might be the column might not be set up as a var(max)
Related
I need to save a pdf file into BLOB (database is MsSql 2012, but I would need it work on 2008 too).
Here is compilation of what I have tried so far:
(File where I save pdf into database)
function preparePDF2String($filepath)
{
$handle = #fopen($filepath, 'rb');
if ($handle)
{
$content = #fread($handle, filesize($filepath));
$content = bin2hex($content);
#fclose($handle);
return "0x".$content;
}
}
$out = preparePDF2String('pdf/pdf.pdf');
$q_blob = "INSERT INTO HISTORIA_ARCHIWUM_test(PDFName, PDFData) VALUES('First test pdf', $out) ";
$r_blob = mssql_query($q_blob,$polacz);
Results (ok, I think)
(Now the php file where I try to output the pdf)
// header('Content-type: application/pdf');
// readfile('pdf/pdf.pdf'); - this works just fine, so pdf is ok
$q_blob = "select top 1 * from HISTORIA_ARCHIWUM_test";
$r_blob = mssql_query($q_blob,$polacz);
$w_blob = mssql_fetch_array($r_blob);
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="the.pdf"');
echo $w_blob['PDFData'];
//echo hex2bin ($w_blob['PDFData']); - I also tried this - same problem
Problem: when I try to output the pdf in the browser I get error (this pdf is of not supported format). It won't open in Adobe reader also. My guess is that I output it wrong, but maybe it is the way I save it?
EDIT from comments
It seems php+mssql truncates string when you get it from db, but its manageable in php.ini. I set mssql.textlimit = 160000 and mssql.textsize = 160000 and it works fine with Hex conversion and varchar(max).
You are transforming the pdf data before you save it to the database, you have to undo the transformation before you output it.
header('Content-type: application/pdf');
header('Content-Disposition: inline; filename="the.pdf"');
echo hex2bin(substr($w_blob['PDFData'], 2));
Also why are you transforming the data in the first place, just save it as binary.
I have the following script that will export data from my database using php to csv file. Everything works fine, except when I try to open the file in excel, I get "file is corrupt". When I run this code it shows the error - "The file is corrupted and can not be opened." Thanks in advance!
<?php
// Connection
include_once('conn.php');
$sql = "select * from info";
$qur = mysql_query($sql);
// Enable to download this file
$filename = "sampledata.csv";
header("Content-Disposition: attachment; filename=\"$filename\"");
header("Content-Type: text/csv");
$display = fopen("php://output", 'w');
$flag = false;
while($row = mysql_fetch_assoc($qur)) {
if(!$flag) {
// display field/column names as first row
fputcsv($display, array_keys($row), ",", '"');
$flag = true;
}
fputcsv($display, array_values($row), ",", '"');
}
fclose($display);
exit;
?>
I found the answer of my own question. Just need to add the ob_clean() line before we call the headers to download csv file to clear the output buffer. This will solve the error of not opening csv file in excel.
From a php script (PHP 5.3.10-1 on Ubuntu3.6) I connect to an MSSQL Server and I would like to retrive image data from image field type. And I want to print it.
I can get the data from MSSQL but I can't print/echo it as a valid image. How can I print/echo/save it?
$db= new PDO('odbc:MYODBC', '***', '***');
$stmt = $db->prepare("USE database");
$stmt->execute();
$tsql = "SELECT image
FROM Pics
WHERE id = 12";
$stmt = $db->prepare($tsql);
$stmt->execute();
$stmt->bindColumn(1, $lob, PDO::PARAM_LOB);
$stmt->fetch(PDO::FETCH_BOUND);
header("Content-Type: image/jpg");
echo($lob); //not an image: 424df630030000000000360000002800 ...
imagecreatefromstring($lob); // Data is not in a recognized format ...
$lob = fopen('data://text/plain;base64,' . base64_encode($lob), 'r'); //Resource
fpassthru($lob); //not an image: 424df63003000000000036000000280000 ...
PHP script encoding: UTF-8.
In /etc/freetds/freetds.conf
[MYODBC]
host = myhost.com
client charset = UTF-8
tds version = 7
((With sqlsrv on the server of MSSQL I could use this:
$image = sqlsrv_get_field( $stmt, 0,
SQLSRV_PHPTYPE_STREAM(SQLSRV_ENC_BINARY));
header("Content-Type: image/jpg");
fpassthru($image);
))
UPDATE:
echo base64_decode($lob); //Not an image: γnτΣ}4ΣM4ΣM4ί4ΣM4ΫΝ4ΣM4s...
Try adding the following headers :
Content-Disposition
Content-Transfer-Encoding
Content-Length
In PHP code :
header('Content-Type: image/jpg');
header('Content-Disposition:attachment; filename="my_file.jpg"');// Set the filename to your needs
header('Content-Transfer-Encoding: binary');
header('Content-Length: 12345');// Replace 12345 with the actual size of the image in bytes
I was recently fighting with a similar storage issue. It turned out that I was quoting my binary image data before insert into the database table. So, make sure you are not adding quotes and turning it into a string - like I accidentally did.
Here's the prep work that is done on an existing local file to get the proper data to store into your database. Also, make sure you have bin2hex() available or get a replacement version of the function.
function prepareImageDBString($filepath) {
$out = 'null';
$handle = #fopen($filepath, 'rb');
if ($handle) {
$content = #fread($handle, filesize($filepath));
// bin2hex() PHP Version >= 5.4 Only!
$content = bin2hex($content);
#fclose($handle);
$out = "0x" . $content;
}
return $out;
}
I hope this helps someone.
This must be common asked question, But I could not find from google. We have a table and has photo column in bytea type in postgresql.
We are saving upcoming image with this snippet:
$photo->attributes = $_FILES['Photo'];
$file = CUploadedFile::getInstance($photo, 'photo');
$path = Yii::app()->basePath . '/data/' . $file->name;
$file->saveAs($path); //save the file to the $path
$fp = fopen($path, 'rb');
$content = fread($fp, filesize($path)); //get the file content
fclose($fp);
$photo->photo = base64_encode($content); //encode it
$photo->save(); //save the record to db
unlink(Yii::app()->basePath . '/data/' . $file->name);
saving seems working good.
this is where we are reading blob field from db:
base64_decode($data->photo) //this call is giving base64_decode() expects parameter 1 to be string, resource given error.
if I do:
print_r($data->photo) //I am getting: Resource id #51
Obviously $data->photo is not binary string, it is coming as a resource. Any idea how to make it work?
thanks in advance.
If you're using base64 then you don't need bytea, you can use a regular text field. It'll be less efficient for disk space, but that's about it.
If you want to store the actual bytes, you don't encode it as base64, you use pg_escape_bytea to convert it to PostgreSQL's hex-string representation (for modern PostgreSQL versions) of bytea values. You use pg_bytea_decode when extracting the data.
If you're using PDO instead of the native PostgreSQL driver, look up how to work with bytea using PDO. You haven't actually shown your database code at all, only some wrapper for it, so it's very hard to tell what's going on.
Of course, all this only applies to PHP; most languages have separate data types for "textual data" and "binary data" that let the client library automatically convert binary data without you having to jump through escape/unescape hooks.
For me work this solution:
Save file to DB:
$file = CUploadedFile::getInstanceByName('file');
if ($file!=null) {
$fp = fopen($file->tempName,'r');
$content = fread($fp, $file->size);
fclose($fp);
$doc->doc=null; //bytea field
$doc->docname = $file->name;
$doc->mime = $file->type;
$doc->size = $file->size;
$doc->save();
$msg = $doc->getErrors();
$command = Yii::app()->db->createCommand('UPDATE '.
$doc->tableName().' SET "doc"=:doc WHERE id='.$doc->id);
$command->bindParam(":doc", $content, PDO::PARAM_LOB); // <-- look this!
$command->execute();
}
Show file from DB:
header('Content-Type: '.$doc->mime );
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename*=UTF-8\'\'' . rawurlencode ($doc->docname ) );
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . $doc->size);
$content = fread($doc->doc, $doc->size);
echo $content;
exit;
I have a simple html form, that saves the email message and multiple attachments path. I am saving the files on the server and their path to the database filed.
Now how can i retrive the files from its path, and then show them to user, when click on Download, I am using the following code for getting the file, but this is not working
$query = "
SELECT `type`, `name`, `size`, `file1`,`file2`,`file3`,`file4`,`file5`
FROM `upload` WHERE `id` = {$id}";
$result = $dbLink->query($query);
if($result) {
if($result->num_rows == 1) {
$row = mysqli_fetch_assoc($result);
header("Content-Type: ". $row['type']);
header("Content-Length: ". $row['size']);
header("Content-Disposition: attachment; filename=". $row['name']);
$path = $row['file1'];
$dir = opendir($path);
echo $dir;
while ($dir && ($file = readdir($dir)) !== false) {
echo $file;
}
The echoed file doesnot contain any data.
This i am doing now for only one file, whose path is at "file1". Similarly i have 5 attachments path, and i have to retrive them all in this code.
Please how can i do it.
First: You can't have more than one download like this. You can only send that header once and that's it.
Is $path the full path to the file? You could try is_readable($file) to check first in a test. Once you have the full path though, it's simple.
header("Content-Type: application/octet-stream");
header("Content-Length: ". $row['size']);
header("Content-Disposition: attachment; filename=". $row['name']);
readfile($row['file1']);
exit();
Readfile outputs directly and streams it, so you don't have to read the content in and then output it. Add the exit to make sure no other output get's added after it, or you could corrupt the file.
This works, assuming $row['file1'] has a correct path!
For multiple files, you have to make multiple calls. Like give the user mutliple links they can click on for downloads.
The only alternative is that you pack it together using zip for example, and send it as one large zipfile.