首页 > 编程语言 >PHP转换PDF时,因为PDF文档没有嵌入字体

PHP转换PDF时,因为PDF文档没有嵌入字体

时间:2025-01-06 11:14:41浏览次数:1  
标签:convert filename height 文档 usr file PDF PHP

问题描述

项目中,需要将PDF文档转为图像,使用Imagick扩展组件进行转换。结果在转换时,因为PDF文档没有嵌入字体,导致一部份文字无法显示出来。如下图片,下划线部份,下划线上面是有文字的,但是转换后,模糊部份的文字正常显示,下划线上面的文字是空白的。

然后就是各种百度、问AI,无论使用何种方法,比如加入字体文档、修复PDF文档、安装第三方组件等等。
最终解决就是用python写一个api服务,因为服务器是centos的,系统python版本是python2,要使用yum所以再加个docker,最终解决问题。

下面是具体的步骤:

  1. 项目新建一个docker目录,用于存放api服务。
  2. 创建一个Dockerfile,内容如下:
# 使用CentOS 7作为基础镜像
FROM centos:7

# 将当前目录下的Centos-7.repo复制到镜像内的/etc/yum.repos.d/目录下并覆盖原有的CentOS-Base.repo文件
COPY Centos-7.repo /etc/yum.repos.d/CentOS-Base.repo

# 将当前目录下的AdobeSongStd-Light.otf复制到镜像目录/usr/share/fonts/目录下
COPY AdobeSongStd-Light.otf /usr/share/fonts/AdobeSongStd-Light.otf

# 设置工作目录
WORKDIR /home/convert

# 添加端口映射
EXPOSE 30581

# 添加目录挂载 /www/wwwroot/dockerdemo.com/docker
# 这个目录放置的是转换PDF服务的源码文件
VOLUME ["/home/convert", "/www/wwwroot/dockerdemo.com/docker"]

# 使用yum安装相关依赖包
RUN yum install -y openssl-devel bzip2-devel libffi-devel zlib-devel poppler-utils gcc gcc-c++ make

# 下载Python 3.8.17的源码包并解压
RUN curl -O https://mirrors.huaweicloud.com/python/3.8.17/Python-3.8.17.tgz && \
    tar -zxvf Python-3.8.17.tgz && \
    cd Python-3.8.17 && \
    # 编译安装Python 3.8
   ./configure --prefix=/usr/local/python3.8 && \
    make && \
    make install && \
    # 备注系统自带的python2.7
    mv /usr/bin/python /usr/bin/python.bak && \
    # 创建软链接将系统默认的python指向python3.8(此操作需谨慎,可能影响依赖Python 2的系统命令)
    ln -s /usr/local/python3.8/bin/python3.8 /usr/bin/python && \
    # 创建软链接将pip3.8映射到系统目录便于使用
    ln -s /usr/local/python3.8/bin/pip3.8 /usr/bin/pip

# 使用pip安装指定版本的Pillow以及其他依赖库
RUN pip install Pillow==8.4 flask pdf2image PyPDF2 websockets redis

# 设置容器启动时执行的命令为运行autorun.sh文件(需确保该文件存在于挂载的/home/convert目录下)
CMD ["./autorun.sh"]
  1. 创建autorun.sh文件,内容如下:
#!/bin/bash
# 切换到.py文件所在目录(假设.py文件在/app目录下,根据实际情况修改)
cd /home/convert
# 运行.py文件(假设文件名为main.py,根据实际情况修改)
python main.py

  1. 创建main.py文件,内容如下:
#!/usr/bin/env python3
from flask import Flask, request, jsonify, send_from_directory
import os
from pdf2image import convert_from_bytes
from PIL import Image
import uuid
from werkzeug.utils import secure_filename

app = Flask(__name__)

# 配置上传和输出目录
UPLOAD_FOLDER = 'upload'
OUTPUT_FOLDER = 'output'
ALLOWED_EXTENSIONS = {'pdf'}

# 确保目录存在
os.makedirs(UPLOAD_FOLDER, exist_ok=True)
os.makedirs(OUTPUT_FOLDER, exist_ok=True)

def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

def process_pdf(pdf_bytes):
    try:
        # 转换PDF为图片,提高DPI到300
        images = convert_from_bytes(
            pdf_bytes,
            dpi=300,
            fmt='png',
            first_page=1,
            last_page=7  # 修改为7页以包含第7页
        )

        # 调整图片宽度为800,高度按比例缩放
        target_width = 800
        first_images = []
        total_height = 0
        
        for img in images:
            # 计算缩放比例
            ratio = target_width / img.width
            new_height = int(img.height * ratio)
            # 调整图片大小,使用 ANTIALIAS 替代 Resampling.LANCZOS
            resized_img = img.resize((target_width, new_height), Image.ANTIALIAS)
            first_images.append(resized_img)
            total_height += new_height
        
        # 创建新图片用于拼接
        result = Image.new('RGB', (target_width, total_height), 'white')
        
        # 拼接图片
        current_height = 0
        for img in first_images:
            result.paste(img, (0, current_height))
            current_height += img.height

        # 生成唯一文件名
        output_filename = f"{uuid.uuid4()}.png"
        
        output_path = os.path.join(OUTPUT_FOLDER, output_filename)
        
        # 保存结果
        result.save(output_path, 'PNG')
        
        # 返回文件的URL
        return (
            f"/download/{output_filename}",
            None
        )
        
    except Exception as e:
        return None, str(e)

@app.route('/convert', methods=['POST'])
def convert_pdf():
    # 添加调试信息
    print("files:", request.files)
    print("form:", request.form)
    print("Content-Type:", request.headers.get('Content-Type'))

    if 'file' not in request.files:
        return jsonify({
            'code': -1,
            'message': '没有文件上传'
        }), 400
        
    file = request.files['file']
    
    if file.filename == '':
        return jsonify({
            'code': -1,
            'message': '没有选择文件'
        }), 400
        
    if not allowed_file(file.filename):
        return jsonify({
            'code': -1,
            'message': '不支持的文件格式'
        }), 400
        
    try:
        # 读取PDF文件内容
        pdf_bytes = file.read()
        
        # 处理PDF
        file_url, error = process_pdf(pdf_bytes)
        
        if error:
            return jsonify({
                'code': -1,
                'message': error
            }), 400
            
        return jsonify({
            'code': 0,
            'message': 'SUCCESS',
            'data': {
                'fileUrl': file_url
            }
        })
        
    except Exception as e:
        return jsonify({
            'code': -1,
            'message': str(e)
        }), 500

@app.route('/download/<filename>')
def download_file(filename):
    return send_from_directory(OUTPUT_FOLDER, filename)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=30581, debug=True) 

  1. 构建镜像:
docker build -t convertPdf:latest .
  1. 运行容器:
docker run -d --name convertPdf -p 30581:30581 \
  -v /www/wwwroot/dockerdemo.com/docker:/home/convert \
  convertPdf
  1. 测试编写PHP上传文件代码,调用API接口:
<?php
$client = new Client(['verify' => false]);
$response = $client->request('POST', 'http://127.0.0.1:30581/convert', [
    'multipart' => [
        [
            'name' => 'file',
            'contents' => fopen('/path/to/file.pdf', 'r') // 上传文件路径
        ]
    ],
    'headers' => [
        'Accept' =>'application/json'
    ]
]);
$status_code = $response->getStatusCode();
$body = $response->getBody();
$data = json_decode($body, true);

echo $data['data']['fileUrl']; // 图片URL
  1. 测试上传文件,查看结果。

  2. 注意:如果遇到问题,可以先尝试删除容器、镜像、挂载目录,然后重新构建、运行。

标签:convert,filename,height,文档,usr,file,PDF,PHP
From: https://www.cnblogs.com/quaki/p/18654836

相关文章

  • 群晖NAS如何使用Synology Office实现远程多人同时在线编辑文档
    文章目录前言1.本地环境配置2.制作本地分享链接3.制作公网访问链接4.公网ip地址访问您的分享相册5.制作固定公网访问链接前言群晖NAS的SynologyOffice套件是一个功能强大的办公助手,支持多人同时在线编辑Word、Excel或PPT文档。你可以在办公室里轻松实现团队协......
  • 基于java的SpringBoot/SSM+Vue+uniapp的德云社票务系统的详细设计和实现(源码+lw+部署
    文章目录前言详细视频演示具体实现截图技术栈后端框架SpringBoot前端框架Vue持久层框架MyBaitsPlus系统测试系统测试目的系统功能测试系统测试结论为什么选择我代码参考数据库参考源码获取前言......
  • java ssm基于Android的远程家庭健康监测管理系统uniapp(源码+文档+运行视频+讲解视频)
     文章目录系列文章目录前言一、开发介绍二、详细视频演示三、项目部分实现截图四、uniapp介绍五、系统测试六、代码参考源码获取目的摘要:基于JavaSSM和Android的远程家庭健康监测管理系统为家庭健康管理带来了新的方式。该系统借助UniApp实现多平台使用,方便......
  • PHP伪协议:理解与安全防护
    一、引言在PHP开发中,伪协议(Wrapper)是一种特殊的协议,用于访问本地文件系统和网络资源。PHP提供了多种伪协议,如file://、php://、data://等,它们在开发中有着广泛的应用。然而,伪协议的不当使用也可能带来安全隐患。本文将详细介绍PHP伪协议的常见类型、应用场景以及安全防护措......
  • Python数据结构与算法分析 第3版PDF、EPUB免费下载
    适读人群:1.希望学习数据结构和算法的Python用户;2.计算机专业的学生和老师。只有洞彻数据结构与算法,才能真正精通Python!热门计算机科学教材,华盛顿大学、北京大学等多家高校采用,让你在代码编写的战场上所向披靡!电子版仅供预览,下载后24小时内务必删除,支持正版,喜欢的请购买正版......
  • 动手深度学习-PyTorch(第二版)PDF、EPUB免费下载
    电子版仅供预览,下载后24小时内务必删除,支持正版,喜欢的请购买正版书籍点击原文去下载书籍信息作者:阿斯顿·张(AstonZhang)/李沐(MuLi)/[美]扎卡里·C.立顿(ZacharyC.Lipton)/[德]亚历山大·J.斯莫拉(AlexanderJ.Smola)出版社:人民邮电出版社出品方:异步图书译......
  • Effective Java中文版(原书第3版)PDF、EPUB免费下载
    EffectiveJava中文版(原书第3版)PDF、EPUB免费下载适读人群:本书并非面向Java初学者,而是要求读者有一定的Java编程经验。对于在Java开发方面已经积累一定经验的读者而言,本书可以帮助其更深入地理解Java编程语言,以成为更卓越、高效的Java开发人员。Jolt获奖作品全新升级,与《Java编......
  • Java核心技术·卷 II(原书第11版):高级特性PDF、EPUB免费下载
    适读人群:使用Java技术进行实际项目开发的编程人员针对JavaSE9、10和11全面升级,畅销20载的大师之作,Jolt大奖得主,全球百万Java工程师口碑选择,提供部分作者亲授视频+海量示例代码电子版仅供预览,下载后24小时内务必删除,支持正版,喜欢的请购买正版书籍点击原文去下载书籍信息作......
  • Java基于springboot+vue的宠物领养寄养救助系统pythgon+nodejs+php-计算机毕业设计
    目录功能和技术介绍具体实现截图开发核心技术:开发环境开发步骤编译运行核心代码部分展示系统设计详细视频演示可行性论证软件测试源码获取功能和技术介绍该系统基于浏览器的方式进行访问,采用springboot集成快速开发框架,前端使用vue方式,基于es5的语法,开发工具Intelli......
  • 免费的PDF水印、图片水印软件 —— 笔尖水印
    这两天抽空开发了一个PDF、图片水印软件——笔尖水印。这是一款由JavaFX开发的桌面应用程序、可以批量为PDF或图片添加水印、下面简单介绍笔尖水印这个软件的一些界面和功能:软件界面软件的主界面主要采用BorderPane布局,重写了软件的框架(含最小化,关闭按钮等),中间表格为需要进......