pdf相关工具类(包括docx转pdf,pdf转图片,pdf添加水印)

pdf相关工具类(包括docx转pdf,pdf转图片,pdf添加水印)

最近做项目遇到很多关于pdf的一些需求,在整个过程中遇到了很多问题,在这总结一些我遇到的一些问题和一些坑,并且把整理出来并且测试过的工具类发出来,工具类中可能有很多判断没有做,如果有人需要,请自己完善把。

docx转pdf(注意:是docx)

首先注意一下是docx转pdf,本文主要写的是docx转pdf,暂时只支持docx,千万不要尝试doc改个后缀名就可以用了,并不是的,你可以试下,真的不可以,但是也不是说不可以做到doc转pdf,只是转换的时候需要有应用程序,效率上不是很高,而且很麻烦,不如在需求上做个限制,给产品经理买盒烟把。下面还有几个点需要注意一下;

  • 更新一下本地的字体库,因为工具是依赖本地的字体库的
  • 如果你要上传到服务器上,你要记得把windows下的字体库复制一份到linux下;windows字体在这个路径下: C:\WINDOWS\Fonts, linux下的字体库在这个路径下: /usr/share/fonts;复制好了别忘了敲几行命令把字体生效:
    – mkfontscale
    – mkfontdir
    – fc-cache -fv
pdf转image
  • 没什么特别需要注意的,还是字体库,一定要把字体库弄全!尤其是到linux下,一定要字体库复制过去并生效!
pdf添加水印

这个确实有点恶心,这个依赖的jar包是itext2.1.7的jar包,它所引用的水印字体的配置,并不在jar包内,我查了一下资料,才发现,添加水印时候一定要依赖另一个jar包,我觉得像是一个补丁:iTextAsian.jar,我从maven下载了jar包,并引用,发现并没有什么用,我又找了很多资料,发现这个补丁的包结构和itext的结构不一样,需要修改包结构,终于找到问题,修改一下包结构就ok了,后续会把修改后的jar包贴出来,直接下载引用就好,注意一下jar包版本,由于我用的gradle不是maven,所以贴出来的是gradle地址,不过都是一样的,转一下就好;

工具需要的jar包地址
compile group: 'com.lowagie', name: 'itext', version: '2.1.7'
compile fileTree(dir:'libs', include:['*.jar'])
compile 'org.apache.pdfbox:fontbox:2.0.1'
compile 'org.apache.pdfbox:pdfbox:2.0.1'
compile group: 'fr.opensagres.xdocreport', name: 'org.apache.poi.xwpf.converter.pdf', version: '1.0.4'

iTextAsian.jar 下载地址: https://pan.baidu.com/s/1n6SzXd851_BC-LzWH9BQIA

工具类代码
import com.lowagie.text.DocumentException;
import com.lowagie.text.Element;
import com.lowagie.text.pdf.*;
import fr.opensagres.xdocreport.utils.StringUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.PDFRenderer;
import org.apache.poi.xwpf.converter.pdf.PdfConverter;
import org.apache.poi.xwpf.converter.pdf.PdfOptions;
import org.apache.poi.xwpf.usermodel.*;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author JiShaochen
 * @date 2018/4/14 16:03
 * @desc .
 */
public class PDFUtils {

    public static void main(String[] args){
//        pdfConvertToImage("D:/1.pdf", "D://2");
        try {
//            docConvertToPdf("D:/1.docx", "D:/2.pdf");
            pdfToWatermarkPdf("D:/1.pdf", "D:/3.pdf", "水印文字");
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    /**
     * @Author: ShaoChen
     * @Description: PDF转为多张图片 sourcePath是源文件, targetSource是
     * @Date: 16:07 2018/4/14
     */
    public static Integer pdfConvertToImage(String sourcePath, String targetSource) {
        File file = new File(sourcePath);
        try {
            file.mkdir();
            PDDocument doc = PDDocument.load(file);
            PDFRenderer renderer = new PDFRenderer(doc);
            int pageCount = doc.getNumberOfPages();
            for(int i=0; i<pageCount; i++){
                BufferedImage image = renderer.renderImage(i, 2.5f);
                ImageIO.write(image,"JPG",new File(targetSource+ "/" + i + ".jpg"));
            }
            return pageCount;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * @Author: ShaoChen
     * @Description: 将docx文件转换为Pdf文件, 调用这个方法,后面的配合使用的
     * @Date: 10:30 2018/4/16
     */
    public static void docConvertToPdf(String docxPath, String targetUrl) throws Exception {
        InputStream source = new FileInputStream(docxPath);
        OutputStream target = new FileOutputStream(targetUrl);
        Map<String, String> params = new HashMap<String, String>();
        PdfOptions options = PdfOptions.create();
        wordConverterToPdf(source, target, options, params);
    }

    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     *
     * @param source 源为word文档, 必须为docx文档
     * @param target 目标输出
     * @param params 需要替换的变量
     * @throws Exception
     */
    public static void wordConverterToPdf(InputStream source,
                                          OutputStream target, Map<String, String> params) throws Exception {
        wordConverterToPdf(source, target, null, params);
    }

    /**
     * 将word文档, 转换成pdf, 中间替换掉变量
     *
     * @param source  源为word文档, 必须为docx文档
     * @param target  目标输出
     * @param params  需要替换的变量
     * @param options PdfOptions.create().fontEncoding( "windows-1250" ) 或者其他
     * @throws Exception
     */
    public static void wordConverterToPdf(InputStream source, OutputStream target,
                                          PdfOptions options,
                                          Map<String, String> params) throws Exception {
        XWPFDocument doc = new XWPFDocument(source);
        paragraphReplace(doc.getParagraphs(), params);
        for (XWPFTable table : doc.getTables()) {
            for (XWPFTableRow row : table.getRows()) {
                for (XWPFTableCell cell : row.getTableCells()) {
                    paragraphReplace(cell.getParagraphs(), params);
                }
            }
        }
        PdfConverter.getInstance().convert(doc, target, options);
    }

    /**
     * 替换段落中内容
     */
    private static void paragraphReplace(List<XWPFParagraph> paragraphs, Map<String, String> params) {
        if (!params.isEmpty()) {
            for (XWPFParagraph p : paragraphs) {
                for (XWPFRun r : p.getRuns()) {
                    String content = r.getText(r.getTextPosition());
                    if (StringUtils.isNotEmpty(content) && params.containsKey(content)) {
                        r.setText(params.get(content), 0);
                    }
                }
            }
        }
    }

    /**
     * @Author: ShaoChen
     * @Description:   pdf添加水印
     * @Date: 10:36 2018/4/16
     */
    public static void pdfToWatermarkPdf(String sourceUrl, String targetUrl, String message) throws IOException, DocumentException {
        // 要输出的pdf文件
        BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(targetUrl)));
        // 将pdf文件先加水印然后输出
        setWatermark(bos, sourceUrl, 16, message);
    }

    public static void setWatermark(BufferedOutputStream bos, String input,
                                    int permission, String message) throws DocumentException,
            IOException {

        PdfReader reader = new PdfReader(input);
        PdfStamper stamper = new PdfStamper(reader, bos);
        int total = reader.getNumberOfPages() + 1;
        BaseFont base = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H",BaseFont.EMBEDDED);
        PdfGState gs = new PdfGState();
        for (int i = 1; i < total; i++) {
            /*
               首先介绍一下: 前两个参数是pdf的横纵坐标,可以想象成一个平面直角坐标系,原地在pdf每页的左下角;
               line为x轴;
               height为y轴;
               angle为水印的角度;
               这三个参数自己调整就好
            */
            // 设置第一行水印
            setLineWaterMark(stamper, base, gs, i, 140,1000, 40, message);
            setLineWaterMark(stamper, base, gs, i, 320,1000, 40, message);
            setLineWaterMark(stamper, base, gs, i, 500,1000, 40, message);
            setLineWaterMark(stamper, base, gs, i, 680,1000, 40, message);
            setLineWaterMark(stamper, base, gs, i, 860,1000, 40, message);
            // 设置第二行水印
            setLineWaterMark(stamper, base, gs, i, 140,700, 40, message);
            setLineWaterMark(stamper, base, gs, i, 320,700, 40, message);
            setLineWaterMark(stamper, base, gs, i, 500,700, 40, message);
            setLineWaterMark(stamper, base, gs, i, 680,700, 40, message);
            setLineWaterMark(stamper, base, gs, i, 860,700, 40, message);
            // 设置第三行水印
            setLineWaterMark(stamper, base, gs, i, 140,400, 40, message);
            setLineWaterMark(stamper, base, gs, i, 320,400, 40, message);
            setLineWaterMark(stamper, base, gs, i, 500,400, 40, message);
            setLineWaterMark(stamper, base, gs, i, 680,400, 40, message);
            setLineWaterMark(stamper, base, gs, i, 860,400, 40, message);
            // 设置第四行水印
            setLineWaterMark(stamper, base, gs, i, 140,100, 40, message);
            setLineWaterMark(stamper, base, gs, i, 320,100, 40, message);
            setLineWaterMark(stamper, base, gs, i, 500,100, 40, message);
            setLineWaterMark(stamper, base, gs, i, 680,100, 40, message);
            setLineWaterMark(stamper, base, gs, i, 860,100, 40, message);

        }
        stamper.close();
    }

    private static void setLineWaterMark(PdfStamper stamper, BaseFont base, PdfGState gs, int page, Integer line,
                                         Integer height, Integer angle, String message) {
        PdfContentByte content;
        content = stamper.getOverContent(page);// 在内容上方加水印
//                content = stamper.getUnderContent(i);//在内容下方加水印
        gs.setFillOpacity(0.2f);
        content.setGState(gs);
        content.beginText();
        content.setColorFill(Color.LIGHT_GRAY);
        content.setFontAndSize(base, 16);
        content.setTextMatrix(20, 70);
        content.showTextAligned(Element.ALIGN_CENTER, message, line, height, angle);
        content.setColorFill(Color.BLACK);
        content.setFontAndSize(base, 8);
        content.endText();
    }
}
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值