fpdi将PDF生成图片pdf文件

时间:2022-02-07 10:23:02

类库:GitHub - Setasign/FPDI: FPDI is a collection of PHP classes facilitating developers to read pages from existing PDF documents and use them as templates in FPDF.

要将FPDI与FPDF结合使用,请在composer.json中包含以下内容。

{    
        "require": {        
            "setasign/fpdf": "1.8.*",        
            "setasign/fpdi": "^2.0"
    }
}

要使用TCPDF,请在composer.json中包含以下内容。

{    
        "require": {        
            "tecnickcom/tcpdf": "6.3.*",        
            "setasign/fpdi": "^2.0"
    }
}

要使用tfPDF,请在composer.json中包含以下内容

{    
        "require": {        
            "setasign/tfpdf": "1.31.*",        
            "setasign/fpdi": "^2.3"
    }
}

环境:需要

imagick+ghostscript
否则会一直报错的。
win报错:

微信图片_20220207102235.png

linux会报:failed to read the file

注意:一般网上很多都会提到imagick,但是会忽视ghostscript,其实ghostscript也是必须要的,这里被坑的不行,浪费一天时间,如果不装ghostscript会报‘failed to read the file’ ,看到这个错误一般会想到权限、路径什么的,其实都不是,所以很难排查;

安装扩展:

1. ubuntu安装:

apt-get update && \
apt-get install -y --no-install-recommends libmagickwand-dev && \
pecl install imagick-3.6.0 && \
apt-get install ghostscript
php.ini添加 extension=imagick.so

docker

docker-php-ext-enable imagick

2. centos:

yum install ImageMagick
yum install ImageMagick-devel
pecl install imagick
yum install -y ghostscript

php -m查看是否安装成功

图片.png

图片.png

需要给PDF文档加密及功能限制可以用tcpdf

php生成pdf文件,并且把该文件加密或设置访问密码

开源的TCPDF是基于PHP的一套类库,它能够很好的生成PDF格式的文档。并且支持文件加密,在目前的开源PHP框架、系统、应用中也使用得很广。这里是设置PDF文档的相关属性的方法原型,其中就可以设置密码

GitHub - tecnickcom/TCPDF: Official clone of PHP library to generate PDF documents and barcodes

1

2

3

4

5

6

7

8

TCPDF::SetProtection 

(

$permissions array('print''modify''copy''annot-forms''fill-forms''extract''assemble''print-high'), 

$user_pass ''

$owner_pass = null, 

$mode = 0, 

$pubkeys = null 

)

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

265

266

267

268

269

270

271

272

273

274

275

276

277

278

279

280

281

282

283

284

285

286

287

288

289

290

291

292

293

294

295

296

297

298

299

300

301

302

303

304

305

306

307

308

309

310

311

312

313

314

315

316

317

318

319

320

321

322

323

324

325

326

327

328

329

330

331

332

333

334

335

336

337

338

339

340

341

342

343

344

345

346

347

348

349

350

351

352

353

354

355

356

357

358

359

360

361

362

363

364

365

366

367

368

369

370

371

372

373

374

375

376

377

378

379

380

381

382

383

384

385

386

387

388

389

390

391

392

393

394

395

396

397

398

399

400

401

402

403

404

405

406

407

408

409

410

411

412

413

414

415

416

417

418

419

420

421

422

423

424

425

426

427

428

429

430

431

432

433

434

435

436

437

438

439

440

441

442

443

444

445

446

447

448

<?php

namespace services\info;

use services\CommonService;

use services\users\UserService;

use setasign\Fpdi\Fpdi;

use yii\db\Exception;

use yii\helpers\FileHelper;

/**

 * PDF文件处理服务类

 * Class Pdf2PicService

 * @package services\info

 * @author: luwc

 * @Time: 2022/2/7 10:45

 */

class Pdf2PicService

{

        /**

         * 将pdf每页转化为图并增加水印(优化版)

         * @param $pdf_file

         * @param string $warter_text

         * @param int $quality

         * @param string $picExtension

         * @return string

         * @throws Exception

         * @throws \ImagickException

         * @throws \setasign\Fpdi\PdfParser\CrossReference\CrossReferenceException

         * @throws \setasign\Fpdi\PdfParser\Filter\FilterException

         * @throws \setasign\Fpdi\PdfParser\PdfParserException

         * @throws \setasign\Fpdi\PdfParser\Type\PdfTypeException

         * @throws \setasign\Fpdi\PdfReader\PdfReaderException

         * @throws \yii\base\Exception

         * @author: luwc

         * @Time: 2022/2/7 9:31

         */

        public static function pdf2PngAllWarterAndOss($pdf_file$warter_text 'xxxxxxx资料'$quality = 100, $picExtension 'png')

        {

            $path = PROJECT_PATH . "/data/pdftmp/pic/";

            FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/");

            FileHelper::createDirectory($path);

         

            $pdf new Fpdi();

            //获取页数

            $pageCount $pdf->setSourceFile($pdf_file);

            @ini_set('memory_limit''1024M');

            $ossPath = [];

            //遍历所有页面

            for ($pageNo = 1; $pageNo <= $pageCount$pageNo++) {

                //导入页面

                $templateId $pdf->importPage($pageNo);

                //获取导入页面的大小

                $size $pdf->getTemplateSize($templateId);

                //创建页面(横向或纵向取决于导入的页面大小)

                if ($size['width'] > $size['height']) {

                    $pdf->AddPage('L'array($size['width'], $size['height']));

                else {

                    $pdf->AddPage('P'array($size['width'], $size['height']));

                }

                echo '第' $pageNo '页' . PHP_EOL;

                $pic = self::pdf2png($pdf_file, PROJECT_PATH . "/data/pdftmp/pic/", ($pageNo - 1), $quality$picExtension);

                if (!empty($warter_text)) {

                    $canvas new \Imagick($pic);

                    $width $canvas->getImageWidth();

                    $height $canvas->getImageHeight();

                    $fontsize = 26;

                    $imagickPixel new \ImagickPixel('rgba(204, 204, 204, 0.5)');

                    $font = VENDOR_PATH . '/../common/services/font/simsun.ttc';

                    for ($i = 0; $i ceil($height / 96); $i++) {

                        $x = max([rand(0, $width / 2), rand(0, $width / 2)]) - 48;

                        $y $i * 200 + 96;

                        $draw new \ImagickDraw();

                        $draw->setFont($font);

                        $draw->setFontSize($fontsize);

                        $draw->setFillColor($imagickPixel);

                        $canvas->annotateImage($draw$x$y, -22, $warter_text);

                    }

                    $canvas->writeImage($pic);

                }

                $fileInfo pathinfo($pic);

                $ossPath[] = CommonService::uploadFile($pic$fileInfo['basename']);

            }

            FileHelper::removeDirectory(PROJECT_PATH . "/data/pdftmp/pic/");

            @unlink($pdf_file);

            unset($pdf);

            return $ossPath;

        }

    /**

     * 处理PDF文件

     * 将PDF内容生成图片并将图片传OSS(质量差)

     * @param $pdf_file

     * @param string $warter_text

     * @param int $type

     * @return array

     * @throws \Exception

     * @author: luwc

     * @Time: 2022/2/7 15:46

     */

    public static function pdfWarter2PicAndOss($pdf_file$warter_text 'xxxxxx资料'$type = 2)

    {

        try {

            FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/");

            FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/pic/");

            $pdf new Fpdi();

            $pdf_new new Fpdi();

            //获取页数

            $pageCount $pdf->setSourceFile($pdf_file);

            $flag = false;

            @ini_set('memory_limit''1024M');

            //遍历所有页面

            for ($pageNo = 1; $pageNo <= $pageCount$pageNo++) {

                //导入页面

                $templateId $pdf->importPage($pageNo);

                //获取导入页面的大小

                $size $pdf->getTemplateSize($templateId);

                //创建页面(横向或纵向取决于导入的页面大小)

                if ($size['width'] > $size['height']) {

                    $pdf->AddPage('L'array($size['width'], $size['height']));

                    $pdf_new->AddPage('L'array($size['width'], $size['height']));

                else {

                    $pdf->AddPage('P'array($size['width'], $size['height']));

                    $pdf_new->AddPage('P'array($size['width'], $size['height']));

                }

                echo '第' $pageNo '页' . PHP_EOL;

                $pic = self::pdf2png($pdf_file, PROJECT_PATH . "/data/pdftmp/pic/", ($pageNo - 1), 50);

                $pdf_new->Image($pic, 0, 0, $size['width']);

                if ($flag === false) {

                    self::pngThumb($warter_text$size['width'] * 25, $size['height'] * 25);

                }

                $flag = true;

                //使用导入的页面

                $pdf->useTemplate($templateId);

                /*// Set font

                $pdf->SetFont('Arial', 'B', 16);

                // Move to 8 cm to the right

                $pdf->Cell(80);

                // Centered text in a framed 20*10 mm cell and line break

                $pdf->Cell(20, 10, 'Title', 1, 1, 'C');*/

                if ($type == 1) {

                    //文字水印

                    //不能调整角色,放弃它了

                    //设置字体

                    //$pdf->SetFont('Arial','B','24');

                    $family = ['courier''helvetica''times''symbol''zapfdingbats'];

                    $pdf_new->SetFont('helvetica''U''50');

                    //设置位置 - 加在中间位置

                    $center_x $size['width'] / 2;

                    $center_y $size['height'] / 2;

                    $pdf_new->SetXY($center_x - 200, $center_y + 50);

                    //写入水印 - 中文会乱码 建议使用中文图片

                    $pdf_new->Write(7, 'ROOT_ICO');

                else {

                    //图片水印

//                $center_x = $size['width'] / 2 - 40;

//                $center_y = $size['height'] / 2;

//                $pdf->image(PROJECT_PATH."/public/warter.png", $center_x, $center_y, 80);//中间水印

                    $pdf_new->image(PROJECT_PATH . "/data/pdftmp/warter.png", 0, 0, $size['width']);//全屏背景水印

                }

            }

            unset($pdf);

            // I输出output,D下载download,F保存file_put_contents,S返回return

//          $pdf->Output('I','测试水印',true);

            $info pathinfo($pdf_file);

            $newFile $info['dirname'] . '/1_' $info['basename'];

            @unlink($newFile);

            $pdf_new->Output('F'$newFile, true);

            unset($pdf_new);

            $pdf new Fpdi();

            //获取页数

            $pageCount $pdf->setSourceFile($newFile);

            @ini_set('memory_limit''1024M');

            //遍历所有页面生成图片地址

            $ossPath = [];

            for ($pageNo = 1; $pageNo <= $pageCount$pageNo++) {

                //导入页面

                $templateId $pdf->importPage($pageNo);

                //获取导入页面的大小

                $size $pdf->getTemplateSize($templateId);

                //创建页面(横向或纵向取决于导入的页面大小)

                if ($size['width'] > $size['height']) {

                    $pdf->AddPage('L'array($size['width'], $size['height']));

                else {

                    $pdf->AddPage('P'array($size['width'], $size['height']));

                }

                echo '第2-' $pageNo '页' . PHP_EOL;

                $localUrl = self::pdf2png($newFile, PROJECT_PATH . "/data/pdftmp/pic/", ($pageNo - 1), 50);

                $fileInfo pathinfo($localUrl);

                $ossPath[] = CommonService::uploadFile($localUrl$fileInfo['basename']);

            }

//

            FileHelper::removeDirectory(PROJECT_PATH . "/data/pdftmp/pic/");

            @unlink(PROJECT_PATH . "/data/pdftmp/warter.png");

            @unlink($newFile);

            @unlink($pdf_file);

            unset($pdf);

            echo '完成' . PHP_EOL;

            return $ossPath;

        catch (\Exception $e) {

            throw new \Exception($e->getMessage());

        }

    }

    /**

     * 处理PDF文件

     * 将PDF内容生成图片并生成新的加密

     * @param $pdf_file

     * @param string $warter_text

     * @param int $type

     * @return string

     * @throws \Exception

     * @author: luwc

     * @Time: 2022/2/7 15:46

     */

    public static function pdfWarter2Pic($pdf_file$warter_text 'xxxxxxx资料'$type = 2)

    {

        try {

            FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/");

            FileHelper::createDirectory(PROJECT_PATH . "/data/pdftmp/pic/");

            $pdf new Fpdi();

            $pdf_new new Fpdi();

            //获取页数

            $pageCount $pdf->setSourceFile($pdf_file);

            $flag = false;

            @ini_set('memory_limit''1024M');

            //遍历所有页面

            for ($pageNo = 1; $pageNo <= $pageCount$pageNo++) {

                //导入页面

                $templateId $pdf->importPage($pageNo);

                //获取导入页面的大小

                $size $pdf->getTemplateSize($templateId);

                //创建页面(横向或纵向取决于导入的页面大小)

                if ($size['width'] > $size['height']) {

                    $pdf->AddPage('L'array($size['width'], $size['height']));

                    $pdf_new->AddPage('L'array($size['width'], $size['height']));

                else {

                    $pdf->AddPage('P'array($size['width'], $size['height']));

                    $pdf_new->AddPage('P'array($size['width'], $size['height']));

                }

                echo '第' $pageNo '页' . PHP_EOL;

                $pic = self::pdf2png($pdf_file, PROJECT_PATH . "/data/pdftmp/pic/", ($pageNo - 1), 50);

                $pdf_new->Image($pic, 0, 0, $size['width']);

                if ($flag === false) {

                    self::pngThumb($warter_text$size['width'] * 25, $size['height'] * 25);

                }

                $flag = true;

                //使用导入的页面

                $pdf->useTemplate($templateId);

                /*// Set font

                $pdf->SetFont('Arial', 'B', 16);

                // Move to 8 cm to the right

                $pdf->Cell(80);

                // Centered text in a framed 20*10 mm cell and line break

                $pdf->Cell(20, 10, 'Title', 1, 1, 'C');*/

                if ($type == 1) {

                    //文字水印

                    //不能调整角色,放弃它了

                    //设置字体

                    //$pdf->SetFont('Arial','B','24');

                    $family = ['courier''helvetica''times''symbol''zapfdingbats'];

                    $pdf_new->SetFont('helvetica''U''50');

                    //设置位置 - 加在中间位置

                    $center_x $size['width'] / 2;

                    $center_y $size['height'] / 2;

                    $pdf_new->SetXY($center_x - 200, $center_y + 50);

                    //写入水印 - 中文会乱码 建议使用中文图片

                    $pdf_new->Write(7, 'ROOT_ICO');

                else {

                    //图片水印

//                $center_x = $size['width'] / 2 - 40;

//                $center_y = $size['height'] / 2;

//                $pdf->image(PROJECT_PATH."/public/warter.png", $center_x, $center_y, 80);//中间水印

                    $pdf_new->image(PROJECT_PATH . "/data/pdftmp/warter.png", 0, 0, $size['width']);//全屏背景水印

                }

            }

            unset($pdf);

            // I输出output,D下载download,F保存file_put_contents,S返回return

//          $pdf->Output('I','测试水印',true);

            $info pathinfo($pdf_file);

            $newFile $info['dirname'] . '/1_' $info['basename'];

            @unlink($newFile);

            $pdf_new->Output('F'$newFile, true);

            unset($pdf_new);

            // 安全处理

            $pdf_new new \setasign\Fpdi\Tcpdf\Fpdi();

            $pdf_new->SetAuthor('xxxx', true);

            $pdf_new->SetCreator('xxx', true);

            $pdf_new->SetSubject('xxx', true);

            $pdf_new->SetKeywords('xxx', true);

            $pdf_new->SetTitle($warter_text, true);

            $pdf_new->SetCompression(true);

            $pdf_new->setSourceFile($newFile);

            $pdf_new->SetProtection(['print''modify''copy''annot-forms''fill-forms''extract''assemble''print-high'], '''xxxx');//遍历所有页面

            for ($pageNo = 1; $pageNo <= $pageCount$pageNo++) {

                //导入页面

                $templateId $pdf_new->importPage($pageNo);

                //获取导入页面的大小

                $size $pdf_new->getTemplateSize($templateId);

                //创建页面(横向或纵向取决于导入的页面大小)

                if ($size['width'] > $size['height']) {

                    $pdf_new->AddPage('L'array($size['width'], $size['height']));

                else {

                    $pdf_new->AddPage('P'array($size['width'], $size['height']));

                }

                //使用导入的页面

                $pdf_new->useTemplate($templateId);

            }

            $newFile2 $info['dirname'] . '/2_' $info['basename'];

            $pdf_new->Output($newFile2'F');

//

            FileHelper::removeDirectory(PROJECT_PATH . "/data/pdftmp/pic/");

            @unlink(PROJECT_PATH . "/data/pdftmp/warter.png");

            @unlink($newFile);

            unset($pdf_new);

//            echo '完成' . PHP_EOL;

            return $newFile2;

        catch (\Exception $e) {

            throw new \Exception($e->getMessage());

        }

    }

    /**

     * 将某页PDF文件转成图片

     * @param $pdf PDF文件绝对路径

     * @param $path 图片临时目录

     * @param int $page pdf页

     * @param int $quality 质量默认100

     * @param string $picExtension 图片文件扩展名

     * @return array|string

     * @throws Exception

     * @throws \ImagickException

     * @author: luwc

     * @Time: 2022/1/24 13:18

     */

    public static function pdf2png($pdf$path$page = 0, $quality = 100, $picExtension 'jpg')

    {

        try {

            $im new \Imagick();

            $im->setResolution(120, 120); //设置图像分辨率

            $im->setCompressionQuality($quality); //压缩比

            $im->readImage($pdf "[" $page "]"); //设置读取pdf的第一页

            //$im->thumbnailImage(200, 100, true);//改变图像的大小

            //$im->scaleImage(200,100,true);//缩放大小图像

            $filename $path "/" . md5(time()) . '-' $page '.' $picExtension;

            if ($im->writeImage($filename) == true) {

                $Return $filename;

            }

            return $Return;

        catch (PDOException $e) {

            throw new Exception('数据处理失败' $e->getMessage());

        }

    }

    /**

     * 暂没用

     * 将pdf转化为一个大长图

     * @param $pdf pdf所在路径 (/www/pdf/abc.pdf pdf所在的绝对路径)

     * @param $path 新生成图片所在路径 (/www/pngs/)

     * @param int $quality

     * @param string $picExtension

     * @return string

     * @throws \ImagickException

     * @author: luwc

     * @Time: 2022/2/7 9:31

     */

    public static function pdf2PngAll($pdf$path$quality = 100, $picExtension 'jpg')

    {

        $im new \Imagick();

        $im->setCompressionQuality($quality);

        $im->setResolution(120, 120);//设置分辨率 值越大分辨率越高

        $im->readImage($pdf);

        $canvas new \Imagick();

        $imgNum $im->getNumberImages();

        foreach ($im as $k => $sub) {

            $sub->setImageFormat($picExtension);

            //$sub->setResolution(120, 120);

            $sub->stripImage();

            $sub->trimImage(0);

            $width $sub->getImageWidth() + 10;

            $height $sub->getImageHeight() + 10;

            if ($k + 1 == $imgNum) {

                $height += 10;

            //最后添加10的height

            $canvas->newImage($width$heightnew \ImagickPixel('white'));

            $canvas->compositeImage($sub, \Imagick::COMPOSITE_DEFAULT, 5, 5);

        }

        $canvas->resetIterator();

        $picPath = sprintf('%s%s.%s'$path, self::getRandStr(), $picExtension);

        $canvas->appendImages(true)->writeImage($picPath);

        return $picPath;

    }

    /**

     * 暂没用

     * @return false|string

     * @author: luwc

     * @Time: 2022/2/7 10:59

     */

    public static function getRandStr()

    {

        $str 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890';

        $randStr str_shuffle($str);//打乱字符串

        $rands substr($randStr, 0, 6);

        return $rands;

    }

    /**

     * 水印图片

     * @param string $warter_text

     * @param $width

     * @param $heigh

     * @author: luwc

     * @Time: 2022/1/24 12:40

     */

    public static function pngThumb($warter_text 'xxxxx'$width$heigh)

    {

        $fontsize = 140;

        $font = VENDOR_PATH . '/../common/services/font/simsun.ttc';

        $warter = imagecreatetruecolor($width$heigh);

        $src_white = imagecolorallocatealpha($warter, 255, 255, 255, 127);

        imagefill($warter, 0, 0, $src_white);//替换成白色

        imagecolortransparent($warter$src_white); //将原图颜色替换为透明色

        imagealphablending($warter, false);//这里很重要,意思是不合并颜色,直接用$img图像颜色替换,包括透明色;

        imagesavealpha($warter, true);//这里很重要,意思是不要丢了$thumb图像的透明色;

        $fontcolor = imagecolorallocate($warter, 204, 204, 204);

        for ($i = 0; $i ceil($heigh / 1200); $i++) {

            $x = max([rand(0, $width / 2), rand(0, $width / 2)]) - 400;

            $y $i * 1200 + 400;

            imagettftext($warter$fontsize, 22, $x$y$fontcolor$font, mb_convert_encoding($warter_text'HTML-ENTITIES''UTF-8'));

        }

        imagepng($warter, PROJECT_PATH . '/data/pdftmp/warter.png');

        imagedestroy($warter);

    }

}

遇到的问题:

报这个错误:

attempt to perform an operation not allowed by the security policy `PDF' @ error/constitute.c/IsCoderAuthorized/408

If I want to re-enable PostScript and PDF formats for ImageMagick, I could make the following changes in the file

如果我想为ImageMagick重新启用PostScript和PDF格式,我可以在文件中进行以下更改

/etc/ImageMagick-6/policy.xml

[... about 70 lines deleted ...]
  <!-- disable ghostscript format types -->  <!--
  <policy domain="coder" rights="none" pattern="PS" />
  <policy domain="coder" rights="none" pattern="EPI" />
  <policy domain="coder" rights="none" pattern="PDF" />
  <policy domain="coder" rights="none" pattern="XPS" />
  -->
  <policy domain="coder" rights="read|write" pattern="PDF,PS" /></policymap>

I was interested in generating a PDF file from a series of JPEG scans of pages. So, I didn't need to use "read|write" above. I could have allowed only "write" and still accomplished what I want.

我对从一系列JPEG页面扫描生成PDF文件感兴趣。所以,我不需要使用上面的“读|写”。我本可以只允许“写”并且仍然完成我想要的。

图片.png

Solved: ImageMagick 'not authorized' PDF Error

  • 19
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值