使用 FPDF 将数据库中的图像转换为 PDF
Image from database into PDF using FPDF
我有一张图像从 iPad 应用程序发送到 SQL
数据库。我可以使用以下 php
:
检索此图像并显示在网页中
$img = base64_encode($row['photoData']);
echo "<img src=\"data:image/jpg;charset=utf8;base64, $img\"/>";
这显示正常。我现在想做的是使用 FPDF
将此图像放入 PDF
文档中,但是我正在努力做到这一点。
这个:
$img = base64_encode($row['photoData']);
$pdf->Image($img);
报错:
FPDF error: Image file has no extension and no type was specified:
所以我尝试了这个(虽然我意识到我将不得不看看如何对图像的大小进行排序):
$pdf->Image($img, 20, 20, 20, 20 'JPG');
这给我:
FPDF error: Missing or incorrect image file:
正确的做法是什么?
或者将图片临时保存到服务器,然后将保存的图片放入PDF
文档中会更容易吗?
根据 Docs FPDF::Image
接受文件名作为第一个参数,而不是二进制 blob。
如果要专门使用FPDF
,请先将图像保存到临时文件,然后再将其传递给FPDF::Image
。
要做到这一点,像这样的事情应该可行:
$tmpFile = tempnam(sys_get_temp_dir(), 'fpdfimg');
if (file_put_contents($tmpFile, $row['photoData'])) {
$fpdf->Image($tmpFile);
// save/display image
unlink($tmpFile);
}
或者,如果您只想将图像作为 PDF(没有其他内容)提供,您可以使用 Imagick
:
$im = new \Imagick();
$im->readImageBlob($row['photoData']);
$im->setImageFormat('pdf');
header('Content-Type: application/pdf');
echo $im;
由于 FPDF 不能使用 base64 数据在 PDF 上生成图像,我建议将文件永久保存到磁盘,而不是为每个 PDF 操作编写一个临时文件。
这将为您节省大量 I/O 开销。
假设您的 table 有独特的 photo_id
或 photo_name
伴随 photoData
那么您可以使用类似这样的东西来创建您的图像并在 FPDF 中使用它们。
我还假设您有 last_update
和 photo_extension
列。
<?php
$path = '/path/to/fpdf/images/';
$filename = $row['photo_id'].'.'.$row['photo_extension'];
$filepath = $path.$filename;
// If a physical file is not available then create it
// If the DB data is fresher than the file then make a new file
if(!is_file($filepath) || strtotime($row['last_update']) > filemtime($filepath))
{
$result = file_put_contents($filepath, $row['photoData']);
if($result === FALSE)
{
die(__FILE__.'<br>Error - Line #'.__LINE__.': Could not create '.$filepath);
}
}
$pdf->Image($filepath);
如果您计划更新存储在您的数据库中的 photoData
,那么您将必须确保还有一个时间戳列,并将该时间戳与图像的 filemtime($filepath)
进行比较你的磁盘。
正如上面评论中提到的,这可以通过使用流 ("data url") 将图像数据移交给 fpdf 库 而无需 将物理文件写入磁盘:
<?php
// load the 'fpdf' extension
require('fpdf.php');
// just for demonstration purpose, the OP gets the content from a database instead
$h_img = fopen('img.jpg', "rb");
$img = fread($h_img, filesize('img.jpg'));
fclose($h_img);
// prepare a base64 encoded "data url"
$pic = 'data://text/plain;base64,' . base64_encode($img);
// extract dimensions from image
$info = getimagesize($pic);
// create a simple pdf document to prove this is very well possible:
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Hello Image!');
$pdf->Image($pic, 10, 30, $info[0], $info[1], 'jpg');
$pdf->Output();
如果这是一个好的建议是另一个问题,这只是为了证明这是可能的...
另一个解决方案;)
通过复制和粘贴这个(编辑过的 fpdf 代码片段)来创建一个新的 php:
require('fpdf.php');
class DATAIMAGE extends FPDF
{
protected function _parsedata($file)
{
// Extract info from a JPEG file
$a = getimagesizefromstring($file);
if(!$a)
$this->Error('Missing or incorrect image file: '.$file);
if($a[2]!=2)
$this->Error('Not a JPEG file: '.$file);
if(!isset($a['channels']) || $a['channels']==3)
$colspace = 'DeviceRGB';
elseif($a['channels']==4)
$colspace = 'DeviceCMYK';
else
$colspace = 'DeviceGray';
$bpc = isset($a['bits']) ? $a['bits'] : 8;
return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$file);
}
}
然后在主 php 中调用此 php 而不是 fpdf.php。
您现在只需在函数末尾添加 'data' 即可显示图像:
$pdf->Image($mysqlrow["blob"],0,0,40,0,'data');
我有一张图像从 iPad 应用程序发送到 SQL
数据库。我可以使用以下 php
:
$img = base64_encode($row['photoData']);
echo "<img src=\"data:image/jpg;charset=utf8;base64, $img\"/>";
这显示正常。我现在想做的是使用 FPDF
将此图像放入 PDF
文档中,但是我正在努力做到这一点。
这个:
$img = base64_encode($row['photoData']);
$pdf->Image($img);
报错:
FPDF error: Image file has no extension and no type was specified:
所以我尝试了这个(虽然我意识到我将不得不看看如何对图像的大小进行排序):
$pdf->Image($img, 20, 20, 20, 20 'JPG');
这给我:
FPDF error: Missing or incorrect image file:
正确的做法是什么?
或者将图片临时保存到服务器,然后将保存的图片放入PDF
文档中会更容易吗?
根据 Docs FPDF::Image
接受文件名作为第一个参数,而不是二进制 blob。
如果要专门使用FPDF
,请先将图像保存到临时文件,然后再将其传递给FPDF::Image
。
要做到这一点,像这样的事情应该可行:
$tmpFile = tempnam(sys_get_temp_dir(), 'fpdfimg');
if (file_put_contents($tmpFile, $row['photoData'])) {
$fpdf->Image($tmpFile);
// save/display image
unlink($tmpFile);
}
或者,如果您只想将图像作为 PDF(没有其他内容)提供,您可以使用 Imagick
:
$im = new \Imagick();
$im->readImageBlob($row['photoData']);
$im->setImageFormat('pdf');
header('Content-Type: application/pdf');
echo $im;
由于 FPDF 不能使用 base64 数据在 PDF 上生成图像,我建议将文件永久保存到磁盘,而不是为每个 PDF 操作编写一个临时文件。
这将为您节省大量 I/O 开销。
假设您的 table 有独特的 photo_id
或 photo_name
伴随 photoData
那么您可以使用类似这样的东西来创建您的图像并在 FPDF 中使用它们。
我还假设您有 last_update
和 photo_extension
列。
<?php
$path = '/path/to/fpdf/images/';
$filename = $row['photo_id'].'.'.$row['photo_extension'];
$filepath = $path.$filename;
// If a physical file is not available then create it
// If the DB data is fresher than the file then make a new file
if(!is_file($filepath) || strtotime($row['last_update']) > filemtime($filepath))
{
$result = file_put_contents($filepath, $row['photoData']);
if($result === FALSE)
{
die(__FILE__.'<br>Error - Line #'.__LINE__.': Could not create '.$filepath);
}
}
$pdf->Image($filepath);
如果您计划更新存储在您的数据库中的 photoData
,那么您将必须确保还有一个时间戳列,并将该时间戳与图像的 filemtime($filepath)
进行比较你的磁盘。
正如上面评论中提到的,这可以通过使用流 ("data url") 将图像数据移交给 fpdf 库 而无需 将物理文件写入磁盘:
<?php
// load the 'fpdf' extension
require('fpdf.php');
// just for demonstration purpose, the OP gets the content from a database instead
$h_img = fopen('img.jpg', "rb");
$img = fread($h_img, filesize('img.jpg'));
fclose($h_img);
// prepare a base64 encoded "data url"
$pic = 'data://text/plain;base64,' . base64_encode($img);
// extract dimensions from image
$info = getimagesize($pic);
// create a simple pdf document to prove this is very well possible:
$pdf = new FPDF();
$pdf->AddPage();
$pdf->SetFont('Arial','B',16);
$pdf->Cell(40,10,'Hello Image!');
$pdf->Image($pic, 10, 30, $info[0], $info[1], 'jpg');
$pdf->Output();
如果这是一个好的建议是另一个问题,这只是为了证明这是可能的...
另一个解决方案;)
通过复制和粘贴这个(编辑过的 fpdf 代码片段)来创建一个新的 php:
require('fpdf.php');
class DATAIMAGE extends FPDF
{
protected function _parsedata($file)
{
// Extract info from a JPEG file
$a = getimagesizefromstring($file);
if(!$a)
$this->Error('Missing or incorrect image file: '.$file);
if($a[2]!=2)
$this->Error('Not a JPEG file: '.$file);
if(!isset($a['channels']) || $a['channels']==3)
$colspace = 'DeviceRGB';
elseif($a['channels']==4)
$colspace = 'DeviceCMYK';
else
$colspace = 'DeviceGray';
$bpc = isset($a['bits']) ? $a['bits'] : 8;
return array('w'=>$a[0], 'h'=>$a[1], 'cs'=>$colspace, 'bpc'=>$bpc, 'f'=>'DCTDecode', 'data'=>$file);
}
}
然后在主 php 中调用此 php 而不是 fpdf.php。
您现在只需在函数末尾添加 'data' 即可显示图像:
$pdf->Image($mysqlrow["blob"],0,0,40,0,'data');