pdf转html?pdf转图片

项目有需求,需要在微信直接浏览pdf文件。ios是可以的,安卓微信端就需要先下载,再用其他工具打开pdf,比如QQ浏览器(坑)。

有需求,就要想解决办法。原来的方法是pdf转html,先前提供的思路(后面发现带到坑里去了)。然后就万事找度娘,马上就找到方法了。就是使用pdfdom转换

引用包

	implementation 'net.sf.cssbox:pdf2dom:1.9'
	implementation 'org.apache.pdfbox:pdfbox:2.0.19'
	implementation 'org.apache.pdfbox:pdfbox-tools:2.0.19'

工具类(找的太多了,就不写引用地址了)

import org.apache.pdfbox.pdmodel.PDDocument;
import org.fit.pdfdom.PDFDomTree;

import java.io.*;

/**
 * @description:pdf转html
 * @author:
 * @create: 2020/05/15
 **/
public class PDFToHTMLUtils {
    /*
    pdf转换html
     */
    public static String pdfToHtml(String filePath)  {
        String outputPath = filePath.substring(0,filePath.lastIndexOf(".")+1)+"html";
        byte[] bytes = getBytes(filePath);
//        try() 写在()里面会自动关闭流
        try (BufferedWriter out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(new File(outputPath)),"UTF-8"));){
            //加载PDF文档
            PDDocument document = PDDocument.load(bytes);
            PDFDomTree pdfDomTree = new PDFDomTree();
            pdfDomTree.writeText(document,out);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return outputPath;
    }
    /*
    将文件转换为byte数组
     */
    private static byte[] getBytes(String filePath){
        byte[] buffer = null;
        try {
            File file = new File(filePath);
            FileInputStream fis = new FileInputStream(file);
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            byte[] b = new byte[4*1024];
            int n;
            while ((n = fis.read(b)) != -1) {
                bos.write(b, 0, n);
            }
            fis.close();
            buffer = bos.toByteArray();
            bos.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return buffer;
    }
}

这块代码丝毫没有问题,唯一的缺点就是效率了。1MB的pdf转换需要30秒左右,体积大了9倍,10MB的需要一分钟以上,体积大了五倍。而且会有格式错乱问题。
解决思路是按页解析,这块没找到代码,不知道是不支持还是啥。看源码就算了,懒。还有一个利用jacob.jar这个包完成按页解析的,只是这个jar包支持不太好,还要改环境(以前解析Excel研究过,没成功,看了一会代码,直接pass)

后来看见第三方服务转换的结果,有了想法。转html不行,可以转图片啊。就度娘了一下,果然方法超级多。

一开始用的是 PDFRenderer,说是效率高,就是对中文字符不太友好,需要系统安装字库(没研究)。自己试了,表格文字大把缺失,pass



import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Arrays;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;

/**
 * @description:转换
 * @author: 
 * @create: 2020/05/21
 **/
public class PDFToImage {
        private final int maxPage = 30;

        public Map change(String PDFPath) {
        //按照文件路径读取PDF文档,并将其按页转换为图片
        if (PDFPath == null || "".equals(PDFPath)) {
        }
        PDFFile pdfFile = this.getPdfFile(PDFPath);
        String path = PDFPath.substring(0, PDFPath.lastIndexOf("/")+1);
        String imageFile = PDFPath.substring(PDFPath.lastIndexOf("/") + 1, PDFPath.lastIndexOf("."));
        Map map = this.pdf2Images(pdfFile, path, imageFile);
        return map;
    }

        /**
         * PDF文档读取.
         *
         * @param filePath -- 待读取PDF文件的路径.
         * @return null 或者 PDFFile instance.
         */
        private PDFFile getPdfFile(String filePath) {
        try {
            //load a pdf file from byte buffer.
            File file = new File(filePath);
            RandomAccessFile raf = new RandomAccessFile(file, "r");
            FileChannel channel = raf.getChannel();
            ByteBuffer buf = channel.map(FileChannel.MapMode.READ_ONLY, 0,
                    channel.size());
            PDFFile pdfFile = new PDFFile(buf);

            return pdfFile;
        } catch (Exception ex) {
            ex.printStackTrace();
        }
        return null;
    }

        /**
         * PDF文档按页转换为图片.
         *
         * @param pdfFile       -- PDFFile instance
         * @param imageSavePath -- 图片保存路径.
         * @param fileName      -- 保存图片文件夹名称.
         */
        private Map pdf2Images(PDFFile pdfFile, String imageSavePath, String fileName) {
//        if(pdfFile == null ) { //待转换文档不存在,返回false.
//            return false;
//        }

        //将转换后图片存放于path路径下

        String path = imageSavePath + fileName+"/";
        File filePath = new File(path);
        if (!filePath.exists()) { //判断以文件名命名的文件夹是否存在.
            filePath.mkdirs();
        }

        //取得当前文件夹下的所有jpg格式的文件名.
        String[] imageNames = filePath.list(new ImageFilter());
        if (imageNames.length == 0) { //当前文件夹下没有文件.
            //将pdf文档按页转为图片.
            String imagePath = "";
            try {
                //对转换页数进行限制,最多只转换前maxPage页.
                int pages = pdfFile.getNumPages();
                if (pages > maxPage) {
                    pages = maxPage;
                }

                for (int i = 1; i <= pages; i++) {
                    // draw the page to an image
                    PDFPage page = pdfFile.getPage(i);
                    // get the width and height for the doc at the default zoom
                    Rectangle rect = new Rectangle(0,
                            0,
                            (int) page.getBBox().getWidth(),
                            (int) page.getBBox().getHeight());
                    // generate the image
                    Image img = page.getImage(rect.width, rect.height, // width & height
                            rect, // clip rect
                            null, // null for the ImageObserver
                            true, // fill background with white
                            true // block until drawing is done
                    );

                    BufferedImage tag = new BufferedImage(rect.width,
                            rect.height,
                            BufferedImage.TYPE_INT_RGB);

                    tag.getGraphics().drawImage(img,
                            0,
                            0,
                            rect.width,
                            rect.height,
                            null);


                    imagePath = path + i + ".jpg";
                    FileOutputStream out = new FileOutputStream(imagePath); // 输出到文件流.
                    ImageIO.write(tag, "jpg", out);
                    out.close();
                }
            } catch (Exception ex) {
                ex.printStackTrace();

            }
        }

        //取得当前文件夹下的所有jpg格式的文件名.
        imageNames = filePath.list(new ImageFilter());
        //对文件名排序.
        Arrays.sort(imageNames, new FileNameComparator());

        Map<String, Object> map = new HashMap<>();
//        servletRequest.setAttribute("state", "s");
//        servletRequest.setAttribute("fileName", fileName);
//        servletRequest.setAttribute("imageNames", imageNames);
        map.put("fileName", fileName);
        map.put("imageNames", imageNames);
        return map;
    }

        class FileNameComparator implements Comparator {
            public final int compare(Object first, Object second) {
                String[] fir = ((String) first).split("\\.");
                String[] sec = ((String) second).split("\\.");

                int firstPage = Integer.parseInt(fir[0]);
                int secondPage = Integer.parseInt(sec[0]);
                int diff = firstPage - secondPage;
                if (diff > 0)
                    return 1;
                if (diff < 0)
                    return -1;
                else
                    return 0;
            }
        }
        //图片jpg过滤器类
        class ImageFilter implements FilenameFilter {
            public boolean isImageFile(String fileName) {
                if (fileName.toLowerCase().endsWith("jpg")) {
                    return true;
                } else {
                    return false;
                }
            }


            public boolean accept(File dir, String name) {
                return isImageFile(name);
            }
        }
}

PDFBox,这是目前我最满意的方案,转换速度,大小,清晰度都很满意。(如果有更好的方法,一起交流)

引入的jar包,自己随便建了一个java文件,总是找不到类文件,出错是在没有引入commons-loggin这个jar包,谨记。(如果使用框架,应该不会因为这个出现bug,脑阔疼)

import org.apache.pdfbox.io.MemoryUsageSetting;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.rendering.ImageType;
import org.apache.pdfbox.rendering.PDFRenderer;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.*;

/**
 * @description:转换2
 * @author: 
 * @create: 2020/05/21
 **/
public class PdfBox {

    public void toImage() {
        try {
            File file = new File("F:/**.pdf");
            PDDocument doc = PDDocument
                    .load(file, MemoryUsageSetting.setupTempFileOnly());
//            int pageCount = doc.getPageCount();
            int pageCount = doc.getNumberOfPages();
            System.out.println(pageCount);
            PDFRenderer pdfRenderer = new PDFRenderer(doc);
            BufferedOutputStream outputStream = null;
            String imgPath;
            float dpi=90;
            for (int i = 0; i < 1; i++) {

                imgPath = "F:/**/" + i + ".png";
                outputStream = new BufferedOutputStream(new FileOutputStream(imgPath));
                BufferedImage image = pdfRenderer.renderImageWithDPI(i, dpi, ImageType.RGB);
                ImageIO.write(image, "png", outputStream);
                outputStream.close();

            }
            doc.close();
            System.out.println("over");
        } catch (FileNotFoundException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }

    }
}

至于前台接收,目前我就只想到图片的网络地址和base64,还有其他方法,欢迎留言。
至于另一边,决定采用现成,比较成熟的方案,不用自己受苦受累的再完善这个东西了(我不会说我懒。。。)

代码copy来,copy去,我都忘了从哪来的了,不要在意这些细节。

完结撒花O(∩_∩)O哈哈~。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值