我在数据库中存储了一些基于base64的图像。是否可以使用FPDF将这些数据直接打印在PDF文档中?
图像的数据结构
data:image/png;base64,iVBORw0KGgoAAAANSUhEUg7AAAfQAAACWCAYAAAAonXpvAAAfgUlEQVR4Ae2dC9BuVVnHuSN3QaBENA9h5A2IcJxMj8hUkymoQDfClIkmrQZr1EydMqapnKRMc8JmHLBBHadJJaV0lKQDZCmCQiqQ2KERUFARDhcFDpx /33W tznPe/ 3ttaa9/ a2Z9/32Xvt5nvVbl2evtdfee9dtS27bt4mACJmACJm8ACJtBvArv123xbbwImYAImYAImIAJ26K4HJmACJmACJjAAAnboAyhEZ8EETMAETMAE7NBdB0zABEzABExgAATs0AdQiM6CCZiACZiACdihuw6YgAmYgAmYwAAI2KEPoBCdBRMwARMwAROwQ3cdMAETMAETMIEBELBDH0AhOgsmYAImYAImYIfuOmACJm
我认为$pdf->imagepng()
应该是FPDF中正确的函数。
虽然评论建议使用TCPDF解决方案,但我确实想声明,有一种方法可以完全使用FPDF来实现这一点。思维过程是这样的:
- 使用
explode
从URI中剥离data:image/png;base64,
- 用
base64_decode
解码URI - 使用
file_put_contents
将解码后的数据保存到PNG文件中 - 生成PDF并使用
Image
添加PNG文件 - 用
unlink
删除PNG文件
永远记得检查错误。如果映像未能保存到服务器,您显然不想继续执行。请务必始终严格检查函数是否返回false!
这是我的解决方案。在这个例子中,我使用了一个小图像作为一个小URI。
const TEMPIMGLOC = 'tempimg.png';
$dataURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAMAAADarb8dAAAABlBMVEUAAADtHCTeKUOwAAAAF0lEQVR4AWOgAWBE4zISkMbDZQRyaQkABl4ADHmgWUYAAAAASUVORK5CYII=";
$dataPieces = explode(',',$dataURI);
$encodedImg = $dataPieces[1];
$decodedImg = base64_decode($encodedImg);
// Check if image was properly decoded
if( $decodedImg!==false )
{
// Save image to a temporary location
if( file_put_contents(TEMPIMGLOC,$decodedImg)!==false )
{
// Open new PDF document and print image
$pdf = new FPDF();
$pdf->AddPage();
$pdf->Image(TEMPIMGLOC);
$pdf->Output();
// Delete image from server
unlink(TEMPIMGLOC);
}
}
我知道这是一个老话题,但有一种更简单的方法可以解决这个问题。只需尝试以下简单步骤:
- 剥离数据:image/png;base64使用爆炸从URI
-
将
data://text/plain;base64,
与剥离的URI中剩下的内容连接起来 - 使用结果字符串(base64)作为FPDF
Image()
的参数
示例:
$dataURI = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAPCAMAAADarb8dAAAABlBMVEUAAADtHCTeKUOwAAAAF0lEQVR4AWOgAWBE4zISkMbDZQRyaQkABl4ADHmgWUYAAAAASUVORK5CYII=";
$img = explode(',',$dataURI,2)[1];
$pic = 'data://text/plain;base64,'. $img;
$pdf = new FPDF();
$pdf->AddPage();
$pdf->Image($pic, 10,30,0,0,'png');
$pdf->Output();
请记住为Image()
方法调用选择正确的图像类型。
为了确保图像与FPDF一起工作并避免错误,这里是@pedro soares代码的修改版本:
function getImage($dataURI){
$img = explode(',',$dataURI,2);
$pic = 'data://text/plain;base64,'.$img[1];
$type = explode("/", explode(':', substr($dataURI, 0, strpos($dataURI, ';')))[1])[1]; // get the image type
if ($type=="png"||$type=="jpeg"||$type=="gif") return array($pic, $type);
return false;
}
因为FPDF只允许这三种文件类型,所以检查它是否有效很重要。使用:
$pic = getImage($Base64StringGoesHere);
if ($pic!==false) $pdf->Image($pic[0], 10,30,0,0, $pic[1]);
不知道为什么到目前为止还没有人写这个解决方案,但我已经成功地将base64字符串直接传递给FPDF的Image()函数。只需确保base64字符串的开头有data:image/png;base64,
即可。
$data = "base64_string.........";
$pdf -> Image($data, 0, 0, 0, 0, "PNG");
请注意,您必须明确指定图像类型";PNG";。40分别表示图像的X、Y宽度和高度。将FPDF的宽度和高度设置为0,以自动使用图像的尺寸。
为了给Mari M的答案添加更多内容,我只添加了几行代码来处理任何类型的图像。(对于我来说,如果图像是jpeg,FPDF会抱怨,并且我试图加载tempimg.png)
$this->tempImgLoc = 'tempimg'; // Here I just remove the file extension
$dataPieces = explode(',',$dataURI);
$encodedImg = $dataPieces[1];
$decodedImg = base64_decode($encodedImg);
// extract the image type from data:image/png;base64
$extension = explode('/', $dataPieces[0]);
$extension = explode(';', $extension[1]);
$this->tempImgLoc .= '.' . $extension[0];
我相信用正则表达式有更好的方法可以做到这一点,但老实说,regexp不是我喜欢的。。。
好吧,我浪费了半天时间来测试这个问题。我必须告诉大家,这个解决方案是直接从数据库行打印图像,而不将它们存储在临时文件中。
我将写一些需要考虑的要点:
- 我在数据库中使用blob类型来存储用于打印pdf文档的人工签名
- 我正在通过post方法从画布节点向数据库发送要存储的签名
- 当我打印数据库blob中的字符串时,它没有加号"+",这使我无法正确打印签名。为了解决这个问题,我制作了一个"str_replace"来删除空格并插入加号
那么你唯一要做的就是:
$pdf->Image(str_replace(' ','+',$dbRow['blobImage']),160,150,20,10,'png');
如果你像我一样需要从数据库打印几个图像,你必须看看它们是否出现,因为如果图像为空,你就会出错。
我只是把这个添加到最后一个代码中:
if( $dbRow['blobImage'] ){
$pdf->Image(str_replace(' ','+',$dbRow['blobImage']),160,150,20,10,'png');
}
注:
- 160->图像的X位置
- 150->图像的Y位置
- 20->图像的X比例
- 10->图像的Y比例
- 'png'->我的Base64图像类型的基本格式
带有imagecreatefromstring()的新解决方案2019年夏季
- 删除临时.png(如果存在)
- 创建临时.png文件
- 使用$pdf->图像(fpdf)
My Api返回1234的Datamatrix作为Byte Array。下面的代码向您展示了如何使用Fpdf中的字节数组作为Png
我的$响应="iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAXNSR0IArs4c6QAAAARnQU1BAACxjv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABJSURBVChTjYwBCgAgCAP9/6dNrevUgg7Gps3EUOfD5Q4Au6YdAGcH8ygyVKrFnhmbc9FL7qRxWRxEkXWW4Q691UsGpZPzt7EFyY47RMW+x2LAAAAAElFTkSuQmCC"
$filename = '/lk_Reptool/printing/tmp/tmppng.png';
if (file_exists($filename)) {
unlink($filename);
}
$response = file_get_contents('https://myapi.com/TwoDCode/GetDatamatrixAsPngByteArray?datamatrixText=' . $RepID . '&pixelSize=100');
$response = base64_decode($response);
$img = imagecreatefromstring($response);
imagepng($img, $filename);
pdf 代码
$pdf = new PDF('P', 'mm', 'A4');
$pdf->AddPage();
$pdf->Image('/lk_Reptool/printing/tmp/tmppng.png', 180, 20, 10, 10);
只需使用以下功能扩展Fpdf(在1.8.1上测试):
protected function _parsepngdata($data) {
$f = tmpfile();
fwrite($f, base64_decode(substr($data, strpos($data,",")+1)));
fseek($f, 0);
$info = $this->_parsepngstream($f,"pngdata");
fclose($f);
return $info;
}
并以这种方式使用它:(提供base64数据而不是文件名,并将类型设置为"pngdata"而不是"png")
$pdf->Image("data:image/png;base64,iVBORw0KGgo...", $x, $y, $w, $h, "pngdata");
它将创建一个临时文件,向/从中写入/读取数据,然后将其删除。