12

我在数据库中有一些作为 base64 存储的图像。是否可以使用 FPDF 直接在 PDF 文档中打印这些数据?

图像的数据结构

data:image/png;base64,iVBORw0KGgoAAAANSUhEUg7AAAfQAAACWCAYAAAAonXpvAAAfgUlEQVR4Ae2dC9BuVVnHuSN3QaBENA9h5A2IcJxMj8hUkymoQDfClIkmrQZr1EydMqapnKRMc8JmHLBBHadJJaV0lKQDZCmCQiqQ2KERUFARDhcFDpx /33W tznPe/ 3ttaa9/ a2Z9/32Xvt5nvVbl2evtdfee9dtS27bt4mACJmACJm8ACJtBvArv123xbbwImYAImYAImIAJ26K4HJmACJmACJjAAAnboAyhEZ8EETMAETMAE7NBdB0zABEzABExgAATs0AdQiM6CCZiACZiACdihuw6YgAmYgAmYwAAI2KEPoBCdBRMwARMwAROwQ3cdMAETMAETMIEBELBDH0AhOgsmYAImYAImYIfuOmACJm

我认为$pdf->imagepng()应该是 FPDF 中的正确功能。

4

8 回答 8

25

虽然评论建议了一个 TCPDF 解决方案,但我确实想说明有一种方法可以完全使用 FPDF 来做到这一点。思考过程是这样的:

  1. data:image/png;base64,使用从 URI 中剥离explode
  2. 使用解码 URIbase64_decode
  3. 将解码后的数据保存到 PNG 文件中file_put_contents
  4. 生成 PDF 并添加 PNG 文件Image
  5. 删除PNG文件unlink

永远记得错误检查。如果图像无法保存到服务器,您显然不想继续执行。确保始终严格检查函数是否返回 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);
    }
}
于 2015-05-14T13:03:44.860 回答
14

我知道这是一个老话题,但是有一种更简单的方法可以解决这个问题。试试这个简单的步骤:

  1. 使用爆炸从 URI 中剥离data:image/png;base64
  2. data://text/plain;base64,与剥离的 URI 中剩余的内容连接
  3. 使用结果字符串(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()方法调用选择正确的图像类型。

于 2017-06-16T01:03:18.883 回答
6

为确保图像适用于 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]);
于 2017-10-22T18:29:26.737 回答
1

好的,我浪费了半天时间来测试这个问题。我不得不说这个解决方案是直接从 db 行打印图像,而不是将它们存储在临时文件中。

我将写一些要考虑的点:

  • 我在数据库上使用 blob 类型来存储人类签名以在 pdf 文档上打印
  • 我正在从画布节点发送签名以通过 post 方法存储到数据库。
  • 当我从 db 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 图像类型的基本格式。
于 2019-04-24T05:17:13.217 回答
1

imagecreatefromstring() Summer 2019的新解决方案

  • 删除临时 .png(如果存在)
  • 创建临时 .png 文件
  • 使用 $pdf-> 图像 (fpdf)

我的 Api 将 1234 的 Datamatrix 作为字节数组返回给我。以下代码向您展示了如何在 Fpdf 中将该字节数组用作 Png。

My $response = "iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAYAAACNMs+9AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAABJSURBVChTjYwBCgAgCAP9/6dNreVUgg7Gps3EUOfD5Q4Au6YdAGcH8ygyVKrFnhmbc9FL7qRxWRxEkXWW4Q691UsGpZPzt7dEFyY47RMW+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);
于 2019-07-23T08:13:57.677 回答
1

为了向 Mari M 答案添加更多内容,我只添加了几行来处理任何类型的图像。(对于我来说,如果图像是 jpeg 并且我尝试加载 tempimg.png,FPDF 会抱怨)

$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];

我确信用正则表达式有更好的方法来做到这一点,但老实说,正则表达式不是我的一杯茶......

于 2016-05-05T22:23:10.173 回答
0

只需使用此函数扩展 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");

它将创建一个临时文件,向/从中写入/读取数据,然后将其删除。

于 2020-10-06T15:16:38.723 回答
0

不知道为什么到目前为止还没有人编写此解决方案,但是我通过将 base64 字符串直接传递给 FPDF 的 Image() 函数而取得了成功。只需确保您的 base64 字符串data:image/png;base64,以开头即可。

$data = "base64_string.........";
$pdf -> Image($data, 0, 0, 0, 0, "PNG");

请注意,您必须明确指定图像类型“PNG”。4 个 0 分别代表图像 X、Y 的宽度和高度。将 FPDF 的宽度和高度设置为 0 以自动使用图像的尺寸。

于 2021-09-06T04:35:51.267 回答