Davide Gualano
Davide Gualano

Reputation: 13003

Save a PDF created with FPDF php library in a MySQL blob field

I need to create a pdf file with the fpdf library and save it in a blob field in my MySQL database. The problem is, when I try to retrieve the file from the blob field and send it to the browser for the download, the donwloaded file is corrupted and does not display correctly.

The same pdf file is correctly displayed if I send it immediately to the browser without storing it in the db, so it seems some of the data gets corrupted when is inserted in the db.

My code is something like this:

$pdf = new MyPDF(); //class that extends FPDF and create te pdf file
$content = $pdf->Output("", "S"); //return the pdf file content as string
$sql = "insert into mytable(myblobfield) values('".addslashes($content)."')";
mysql_query($sql);

to store the pdf, and like this:

$sql = "select myblobfield from mytable where id = '1'";
$result = mysql_query($sql);
$rs = mysql_fetch_assoc($result);
$content = stripslashes($rs['myblobfield']);
header('Content-Type: application/pdf');
header("Content-Length: ".strlen(content));
header('Content-Disposition: attachment; filename=myfile.pdf');
print $content;

to send it to the browser for downloading. What am I doing wrong?

If I change my code to:

$pdf = new MyPDF(); 
$pdf->Output(); //send the pdf to the browser

the file is correctly displayed, so I assume that is correctly generated and the problem is in the storing in the db.

Thanks in advance.

Upvotes: 3

Views: 21080

Answers (7)

Yassine E.
Yassine E.

Reputation: 1

I encountered the same problem as mentioned above, looking more closely at phpmyadmin, I noticed that the insert of a pdf is done in hex, while fpdf returns binary, the solution in my case was to use bin2hex():

$_bin = $_pdf->Ouput("S");
$_hex = "0x" . bin2hex($_bin);

And you can then insert this $_hex in a sql query without using addslashes() or anything... (of course it has to be inserted in a medium or long blob i think)

Upvotes: 0

Orlando Reyes
Orlando Reyes

Reputation: 91

I was recently working with this problem and it is important to give answer after test solutions given by us. Then, I solved this problem as follow. To save generated fpdf i have used this code..:

$content = $pdf->Output("", "S"); 
// addslashes is the key to store blob file
$data = addslashes($content); 
$name = "testname.pdf";
$mime = "application/pdf";
$extficheiro = "pdf";
$nomeficheiro = "miarchivo";
$size = strlen($content);
$query = "INSERT INTO filetable(name, mime, size, data, created)
    VALUES ('$name','$mime', '$size', '$data', NOW())";                      
$conn->query($query);

To read (retrieve from database) from my database was preferable to me use pdo code:

if(filter_has_var(INPUT_GET, "var") !== false && filter_input(INPUT_GET, 'var', FILTER_VALIDATE_INT) !== false)
{
    $var = filter_input(INPUT_GET, "var", FILTER_SANITIZE_NUMBER_INT);
    try     {
        $dbh = new PDO("mysql:host=our_host;dbname=database", 'username', 'password');
        $dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);

        $sql = "SELECT * FROM filetable  WHERE id= ".$var;

        $stmt = $dbh->prepare($sql);
        $stmt->execute(); 
        $stmt->setFetchMode(PDO::FETCH_ASSOC);
        $array = $stmt->fetch();

        /*** set the headers and display the file ***/
        header("Content-Type: ". $array['mime']);
        header("Content-Length: ". $array['size']);/**/
        header("Content-Disposition: inline; filename='". ($array['name'])."'");
        echo $array['data'];
    }
    catch(PDOException $e)
    {
        echo $e->getMessage();
    }
    catch(Exception $e)
    {
        echo $e->getMessage();
    }
}
else
{
    echo '0'; // out of bounds
}

Those codes worked perfectly. I hope this contribution helps others to turn off headache with this problem. Best Regards.

Upvotes: 0

NateDawg
NateDawg

Reputation: 1

SOLVED IT!

I too was having the same problem and was trying the above mentioned ideas. What fixed this for me was that my MySQL database was storing the PDF as a blob instead of mediumblob. A blob field is limited to 64K and was thereby truncating the rest of my PDF which included the valuable data including EOF (hence the nasty Adobe Error).

To confirm, download the PDF file it serves up instead and look at the file size. If it's exactly 64K you'll need to make more room in the DB by setting the field to mediumblob.

Thanks everyone for the help!

By the way, I followed Toto's advice and used mysql_real_escape_string() instead, along with:

  1. Remove stripslashes()
  2. Replace addslashes() by mysql_real_escape_string()

With those changes to the original poster's code it worked!

Upvotes: 0

wakkara
wakkara

Reputation: 11

Replacing

header("Content-Length: ".strlen(content)); 

with

header("Content-Length: ".strlen($content)); 

worked for me.

Upvotes: 1

Toto
Toto

Reputation: 2430

Actually for security reasons:

  1. Do not use addslashes() but use mysql_real_escape_string() instead

In this specific case (as it is binary data):

  1. Remove stripslashes()
  2. Replace addslashes() by mysql_real_escape_string()

Upvotes: 3

Bart
Bart

Reputation: 6814

Compare the differences in the strings to help debug the problem.

$pdf = new MyPDF();
echo $pdf->Output("", "S"); //send the pdf string to the browser
exit;

and

$pdf = new MyPDF(); //class that extends FPDF and create te pdf file
$content = $pdf->Output("", "S"); //return the pdf file content as string
$sql = "insert into mytable(myblobfield) values('".addslashes($content)."')";
mysql_query($sql);
$sql = "select myblobfield from mytable where id = '1'";
$result = mysql_query($sql);
$rs = mysql_fetch_assoc($result);
$content = stripslashes($rs['myblobfield']);
echo $content; //send the pdf string to the browser
exit;

Upvotes: 1

Ignas R
Ignas R

Reputation: 3409

You shouldn't strip any (back)slashes. When you add them, they are used as escape characters in the query and do not appear in the field.

Try changing this

$content = stripslashes($rs['myblobfield']);

into this:

$content = $rs['myblobfield'];

Upvotes: 2

Related Questions