当前位置: 首页 > article >正文

发票打印更方便

前言

由于医疗报销需要,必须大电子票夹(微信小程序)中的发票导出来,打印为纸质版提供给保险公司。目前总结出来最简单的做法是,将需要打印的发票,选中发送到电子邮件中。收到的是一个压缩包,内容为每张发票的pdf文件。要打印这些太麻烦了,还浪费纸。

方案

将压缩包解压,然后将解压出来的pdf中发票内容提取为图片,将图片3张合成一张,最后将所有合成的图片生成pdf打印。以下程序,最后输出的是一个pdf文件。打印的时候需要注意的是,缩放选项,选择【适合纸张大小】

环境

JDK8
itextpdf:5.5.13.3
pdfbox:2.0.17
poi-ooxml:5.2.3
hutool-all:5.8.11

源码

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ZipUtil;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.io.FileUtils;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.pdmodel.PDPage;
import org.apache.pdfbox.pdmodel.PDPageContentStream;
import org.apache.pdfbox.pdmodel.common.PDRectangle;
import org.apache.pdfbox.pdmodel.graphics.image.PDImageXObject;
import org.apache.pdfbox.rendering.ImageType;
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.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * @author dzh
 * @since 2025/1/3
 */
public class PdfImageUtils {

    // 将压缩包中pdf的发票内容提取出来,然后3张为一页,拼接为pdf,方便打印
    public static void main(String[] args) {
        String filePath = "C:/temp/abc.zip";
        File unzipPath = new File(filePath + "_unzip");
        File imageFile = new File(filePath + "_img");
        File mergeFile = new File(filePath + "_merge");
        // 解压
        File file = ZipUtil.unzip(new File(filePath), unzipPath);
        System.out.println(file.getAbsolutePath());

        // 转换为图片
        dealFiles(file, (f) -> {
            toImage(f.getAbsolutePath(), imageFile.getAbsolutePath() + "/" + f.getName() + ".png");
        });
        FileUtil.del(unzipPath);

        // 图片3张合并一张
        imageMerge(imageFile, mergeFile, 3);
        FileUtil.del(imageFile);

        imageToPdf(filePath + ".pdf", mergeFile);
        FileUtil.del(mergeFile);
    }

    public static void imageToPdf(String pdfPath, File imageBaseDir) {

        try (PDDocument document = new PDDocument()) {
            File[] files = imageBaseDir.listFiles();
            if (files == null) {
                return;
            }
            for (File file : files) {
                PDImageXObject pdImage = PDImageXObject.createFromFileByExtension(file, document);
                PDRectangle mediaBox = new PDRectangle(pdImage.getWidth(), pdImage.getHeight());
                PDPage page = new PDPage(mediaBox);
                document.addPage(page);
                PDPageContentStream contentStream = new PDPageContentStream(document, page);

                // 将图片绘制到PDF页面上
                contentStream.drawImage(pdImage, 0, 0);
                contentStream.close();
            }

            document.save(pdfPath);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void dealFiles(File file, Consumer<File> consumer) {
        if (file.isDirectory()) {
            for (File f : Objects.requireNonNull(file.listFiles())) {
                dealFiles(f, consumer);
            }
        } else {
            consumer.accept(file);
        }
    }

    public static void toImage(String pdfFilePath, String outputImagePath) {

        try (PDDocument document = PDDocument.load(new File(pdfFilePath))) {
            if (!document.isEncrypted()) {
                PDFRenderer pdfRenderer = new PDFRenderer(document);
                // 获取第一页的图片
                BufferedImage bufferedImage = pdfRenderer.renderImageWithDPI(0, 300, ImageType.RGB);

                // 保存图片
                File output = new File(outputImagePath);
                FileUtils.createParentDirectories(output);
                ImageIO.write(bufferedImage, "PNG", output);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    public static void imageMerge(File dir, File mergeFile, int size) {
        File[] files = dir.listFiles();
        if (files == null) {
            return;
        }
        List<File> fileList = Arrays.stream(files).collect(Collectors.toList());
        imageMerge(fileList, mergeFile, size);
    }

    private static void imageMerge(List<File> files, File mergeFile, int size) {
        File baseFile = files.get(0).getParentFile();
        String basePath = baseFile.getAbsolutePath();
        files.sort((a, b) -> b.getName().compareTo(a.getName()));
        List<List<File>> partition = ListUtils.partition(files, size);
        String imageDic = mergeFile.getAbsolutePath() + "/";
        for (int i = 0; i < partition.size(); i++) {
            File imageFile = new File(imageDic + i + ".png");
            try {
                FileUtils.createParentDirectories(imageFile);
            } catch (Exception e) {
                // ignore
            }
            imageMerge(partition.get(i), imageFile.getAbsolutePath());
        }
    }

    private static void imageMerge(List<File> files, String target) {
        try {

            BufferedImage[] images = new BufferedImage[files.size()];
            for (int i = 0; i < files.size(); i++) {
                images[i] = ImageIO.read(files.get(i));
            }

            int width = images[0].getWidth();
            int height = Arrays.stream(images).mapToInt(BufferedImage::getHeight).sum();

            // 创建一个新的图片,宽度是两张图片的宽度之和,高度取最大值
            BufferedImage concatenatedImage = new BufferedImage(
                    width,
                    height,
                    BufferedImage.TYPE_INT_RGB);

            // 画图
            Graphics2D g2d = concatenatedImage.createGraphics();

            int startY = 0;
            for (BufferedImage image : images) {
                g2d.drawImage(image, 0, startY, null);
                startY += image.getHeight();
                g2d.drawLine(0, startY, image.getWidth(), startY += 3);
            }
            g2d.dispose();

            // 保存拼接后的图片
            File output = new File(target);
            FileUtils.createParentDirectories(output);
            ImageIO.write(concatenatedImage, "png", output);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


http://www.kler.cn/a/469687.html

相关文章:

  • Docker学习相关笔记,持续更新
  • 科研绘图系列:R语言科研绘图之标记热图(heatmap)
  • haproxy+nginx负载均衡实验
  • 0104java面经
  • 网段划分和 IP 地址
  • 计算机网络 (26)互联网的路由选择协议
  • ubuntu 工具安装
  • TCP协议:三次握手、四次挥手
  • LLM2Vec: 解锁大语言模型的隐藏能力
  • 【每日学点鸿蒙知识】list折叠动画效果、混淆问题定位、bindPopup问题等
  • unity学习11:地图相关的一些基础
  • 极限学习机 (Extreme Learning Machine, ELM) 算法详解与PyTorch实现
  • 猜数字游戏 (C++ 控制台版)
  • 【零基础学Web安全】Web安全基础篇(一)
  • linux 系统 mysql :8.4.3 主从复制 教程及运维命令
  • Leetcode 查找和最小的 K 对数字
  • 【C++】16.stack和queue的使用
  • Python安装(新手详细版)
  • MySQL的sql操作有哪些
  • Go语言的 的基本数据类型(Primitive Data Types)基础知识