跳过APP打开pdf的烦恼,服务端直接将pdf转图片,别踩乱码之坑

手机端APP需要展示pdf文件内容,如果直接用APP打开pdf,将会是一个很大的烦扰,需要解决安卓和苹果同时兼容,这样实现务必会耗费比较多的时间,其实可以采取曲线救国的策略,服务器把pdf进行处理,其中一种就是将pdf转成图片,这样APP基本无需处理。

后端采用的java,把pdf转换图片后,有几页pdf文件就会生成几个图片,如果只需要一个图片,进行合并即可。

调错过程

刚开始的时候本地测试没有问题,但是上了服务器,发现有部分转图片后格式不正确,看日志发现有个提示

No glyph for 47286 (CID 06b1) in font SimSun

刚开始默认认为是字体库缺少,然后从windows上这个目录C:\Windows\Fonts,找到了字体库进行了Linux服务器的字体更新,但经过测试发现并没有什么作用

跳过APP打开pdf的烦恼,服务端直接将pdf转图片,别踩乱码之坑

字体更新方法:

  • #cd /usr/share/fonts/ // 进入系统自带的字体目录
  • #mkdir myfonts // myfonts 是你自己随便取得文件夹名字,一定要有这一步
  • #将字体文件拷贝到这个文件夹下,在cd /usr/share/fonts/目录下执行以下命令
  • #mkfontscale
  • #mkfontdir
  • #fc-cache -fv //更新字体缓存
  • #fc-list // 查看系统中所有的字体,可用于测试是否安装字体成功

尝试是否是jar包问题

后来尝试考虑引入字体库jar包试试,引入了com.itextpdf的itext-asian和itextpdf,经过测试果然没有问题了

下面是所有代码,pdf转图片,图片合并,如果有需要可以图片压缩

引入包:pdfbox需要2.0以上,以下不支持转图片

<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>pdfbox</artifactId>
    <version>2.0.4</version>
</dependency>
<dependency>
    <groupId>org.apache.pdfbox</groupId>
    <artifactId>fontbox</artifactId>
    <version>2.0.4</version>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext-asian</artifactId>
    <version>5.2.0</version>
    <scope>compile</scope>
</dependency>
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itextpdf</artifactId>
    <version>5.5.9</version>
    <scope>compile</scope>
</dependency>

pdf转图片

* PDF文件转PNG/JPEG图片

* @param PdfFilePathpdf完整路径

* @param imgFilePat*图h**片存放的文件夹

* @param dpi越大转换后越清晰,相对转换速度越慢,一般电脑默认96dpi

import com.lowagie.text.pdf.PdfReader;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

public static String pdf2ImageDemo(String PdfFilePath,
       String dstImgFolder, int dpi) {
        String outMixPicUrl="";
    String outMixPicUrl="";
    File file = new File(PdfFilePath);
    PDDocument pdDocument;
    try {
        String imgPDFPath = file.getParent();
        int dot = file.getName().lastIndexOf('.');
        // 获取图片文件名        String imagePDFName = file.getName().substring(0, dot);
        String imgFolderPath = null;
        if (dstImgFolder.equals("")) {
            // 获取图片存放的文件夹路径            imgFolderPath = imgPDFPath + File.separator + imagePDFName;
        } else {
            imgFolderPath = dstImgFolder;
        }

        if (createDirectory(imgFolderPath)) {
            pdDocument = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(pdDocument);
            PdfReader reader = new PdfReader(PdfFilePath);
            int pages = reader.getNumberOfPages();// 获取PDF页数            System.out.println("PDF page number is:" + pages);
            StringBuffer imgFilePath = null;
            List<String> inputFileNameList=new ArrayList<String>();
            for (int i = 0; i < pages; i++) {
                String imgFilePathPrefix = imgFolderPath
                        + File.separator + imagePDFName;
                imgFilePath = new StringBuffer();
                imgFilePath.append(imgFilePathPrefix);
                imgFilePath.append("_");
                imgFilePath.append(String.valueOf(i + 1));
                imgFilePath.append(".png");// PNG                File dstFile = new File(imgFilePath.toString());
                BufferedImage image = renderer.renderImageWithDPI(i, dpi);
                ImageIO.write(image, "png", dstFile);// PNG                inputFileNameList.add(imgFilePath.toString());
            }
            pdDocument.close();
            //图片合并            outMixPicUrl=imgFolderPath + File.separator + imagePDFName+".png";
            append(inputFileNameList,outMixPicUrl,false);
            System.out.println("PDF文档转PNG图片成功!");
        } else {
            System.out.println("PDF文档转PNG图片失败:"                    + "创建" + imgFolderPath + "失败");
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
    return outMixPicUrl;
}

private static boolean createDirectory(String folder) {
    File dir = new File(folder);
    if (dir.exists()) {
        return true;
    } else {
        return dir.mkdirs();
    }
}

图片合并

public static void append(List<String> inputFileNameList, String outputFileName, boolean isX) {
    System.out.println(inputFileNameList.get(0));
    System.out.println(outputFileName);
    if (inputFileNameList == null || inputFileNameList.size() == 0) {
        return;
    }

    try {
        boolean isFirstPng = true;
        BufferedImage outputImg = null;
        int outputImgW = 0;
        int outputImgH = 0;
        for (String pngFileName : inputFileNameList) {
            if (isFirstPng) {
                isFirstPng = false;
                outputImg = ImageIO.read(new File(pngFileName));
                outputImgW = outputImg.getWidth();
                outputImgH = outputImg.getHeight();
            } else {
                BufferedImage appendImg = ImageIO.read(new File(pngFileName));
                int appendImgW = appendImg.getWidth();
                int appendImgH = appendImg.getHeight();

                if (isX) {
                    outputImgW = outputImgW + appendImgW;
                    outputImgH = outputImgH > appendImgH ? outputImgH : appendImgH;
                } else {
                    outputImgW = outputImgW > appendImgW ? outputImgW : appendImgW;
                    outputImgH = outputImgH + appendImgH;
                }

                // create basic image                Graphics2D g2d = outputImg.createGraphics();
                BufferedImage imageNew = g2d.getDeviceConfiguration().createCompatibleImage(outputImgW, outputImgH,
                        Transparency.TRANSLUCENT);
                g2d.dispose();
                g2d = imageNew.createGraphics();

                int oldImgW = outputImg.getWidth();
                int oldImgH = outputImg.getHeight();
                g2d.drawImage(outputImg, 0, 0, oldImgW, oldImgH, null);
                if (isX) {
                    g2d.drawImage(appendImg, oldImgW, 0, appendImgW, appendImgH, null);
                } else {
                    g2d.drawImage(appendImg, 0, oldImgH, appendImgW, appendImgH, null);
                }

                g2d.dispose();
                outputImg = imageNew;
            }
        }
        writeImageLocal(outputFileName, outputImg);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static void writeImageLocal(String fileName, BufferedImage image) {
    if (fileName != null && image != null) {
        try {
            File file = new File(fileName);
            ImageIO.write(image, "png", file);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}