多张图片导出PDF

该博客介绍了如何利用itextpdf库将多张图片转换为PDF文件,按照每页一张图片的方式填充,并设置了图片在页面中的位置和大小。代码示例详细展示了如何处理图片的等比缩放、居中对齐以及导出和下载PDF文件的过程。同时,作者提到在实际操作中遇到图片质量损失的问题,这是一个常见的挑战,目前尚未找到有效的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本文将提供多张图片(示例中为图片地址)导出到PDF,使用itextpdf包对导出进行处理;按照一页一图的方式进行填充到PDF,再进行下载导出;并设置图片在纸张的位置以及大小,可调整边距。

一、引入itextpdf依赖

        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itextpdf</artifactId>
            <version>5.4.2</version>
        </dependency>

二、图片填充到PDF的处理代码

    /**
     * 将图片转换为PDF文件(传入多个图片文件集合,生成多页PDF)
     * @author caiji
     * @param pdfFileName pdf文件名
     * @param fileUrl  图片地址
     * @param paperType 纸张类型对象
     * @return java.io.File
     * @date 2022/2/22 14:49
     */
    public static File generatePdfFile(String pdfFileName, List<String> fileUrl, Rectangle paperType) throws IOException, DocumentException {
        Document doc = new Document(paperType);
        PdfWriter.getInstance(doc, new FileOutputStream(pdfFileName));
        doc.open();
        for (String url : fileUrl) {
            byte[] byteData = getFileByte(url);
            Image image = Image.getInstance(byteData);
            float height = image.getHeight();
            float width = image.getWidth();
            //获取同比压缩比例
            int percent = getPercent(height, width,paperType);
            //设置同比压缩
            if(0 != percent) {
                image.scalePercent(percent);
            }
            //设置左右居中
            image.setAlignment(Image.MIDDLE);
            //根据纸张高度和压缩后的高度计算 设置上边距,保持上下居中(未找到设置上下居中的方法)
            //注意:如果是横向,要取pageSize.getWidth(),这里不会因为横向改变而改变高宽属性
            float marginTop = (paperType.getHeight()-image.getScaledHeight())/2;
            doc.setMargins(0,0,marginTop,0);
            //新起一页,如果写在for的第一行,第一张不会生效
            doc.newPage();
            doc.add(image);
        }
        doc.close();
        File pdfFile = new File(pdfFileName);
        return pdfFile;
    }


    /**
     *
     * 用于下载PDF文件
     *
     * @param pdfFile PDF文件
     * @param response HttpServletResponse
     * @throws IOException IO异常
     */
    public static void downloadPdfFile(File pdfFile, HttpServletResponse response) throws IOException {
        FileInputStream fis = new FileInputStream(pdfFile);
        byte[] bytes = new byte[fis.available()];
        fis.read(bytes);
        fis.close();
        response.reset();
        response.setHeader("Content-Type", "application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(pdfFile.getName(), "UTF-8"));
        OutputStream out = response.getOutputStream();
        out.write(bytes);
        out.flush();
        out.close();
    }



    /**
     * 等比压缩,获取压缩百分比
     *
     * @param height 图片的高度
     * @param width 图片的宽度
     * @param paperType 纸张类型对象
     * @return 压缩百分比
     */
    private static int getPercent(float height, float width, Rectangle paperType) {
        float percent = 0.0F;
        //获取纸张与图片的高、宽比例;这里减30是周边15,打印后周边距离约为10毫米即1厘米
        float percentHeight = (paperType.getHeight()-30) / height * 100;
        float percentWidth = (paperType.getWidth()-30) / width * 100;
        //如果图片高或宽存在超出(此处比较高宽也要跟纸张减去30比,不然上面的留缝隙就没意义)
        // 取高宽比较小的比例,避免压缩后存在另一边还需要压缩
        if(height>(paperType.getHeight()-30) || width>(paperType.getWidth()-30)) {
            percent = percentHeight<percentWidth?percentHeight:percentWidth;
        }
        return Math.round(percent);
    }


    /**
     * 获取文件字节流
     * @author caiji
     * @param fileUrl
     * @return byte[]
     * @date 2022/1/6 12:40
     */
    public static byte[] getFileByte(String fileUrl) throws IOException{
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        InputStream in = null;
        try{
            // 创建URL
            URL url = new URL(fileUrl);
            byte[] by = new byte[1024];
            // 创建链接
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            in = conn.getInputStream();
            int buf_size = 1024;
            byte[] buffer = new byte[buf_size];
            int len = 0;
            while (-1 != (len=in.read(buffer,0,buf_size))){
                bos.write(buffer,0,len);
            }
            return bos.toByteArray();
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try {
                in.close();
            }catch (IOException e){
                e.printStackTrace();
            }
            bos.close();
        }
        return null;
    }

三、传入图片地址,调用并生成PDF

    /**
     * 根据图片地址导出PDF
     * @author caiji
     * @param fileUrl
     * @param paperType 纸张类型对象 A4、A3等
     * @param response
     * @return void
     * @date 2022/1/6 12:40
     */
    public void imageToPdf(String pdfFileName, List<String> fileUrl, Rectangle paperType, HttpServletResponse response){
        try {
            //先生成PDF,再进行下载导出
            File pdfFile = FileHandleUtil.generatePdfFile(pdfFileName,fileUrl,paperType);
            FileHandleUtil.downloadPdfFile(pdfFile, response);
            pdfFile.delete();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

这块不说太多,方法内的注释都已说明,学习阶段,若有问题请随便提~~~

问题说明:我测试是使用前端传输的Base64转成图片后再处理填充到PDF,处理过程中存在图片有些许失帧问题,这个暂未提供有效处理,还得继续研究文档,网上看的一些都是说这个操作是肯定的有失帧,避免不了。。。。。。

### Java 使用模板导出 PDF 并嵌入多张图片 为了实现基于模板的 PDF 文件创建并嵌入多个图像,可以采用 iText 库来操作现有的 PDF 模板。iText 是一个强大的工具集,允许开发者轻松处理 PDF 文档中的各种元素。 下面是一段示例代码,展示了如何利用 `PdfStamper` 类加载预定义好的 PDF 模板,并向其中添加若干幅位图: ```java import com.itextpdf.text.Image; import com.itextpdf.text.pdf.PdfContentByte; import com.itextpdf.text.pdf.PdfReader; import com.itextpdf.text.pdf.PdfStamper; public class TemplateWithImages { public static void main(String[] args) throws Exception { String src = "report_template.pdf"; // 原始模板路径 String dest = "output_with_images.pdf"; // 输出目标 PdfReader reader = new PdfReader(src); try (PdfStamper stamper = new PdfStamper(reader, new FileOutputStream(dest))) { int pageN = reader.getNumberOfPages(); for(int p=1; p<=pageN;p++) { Image img1 = Image.getInstance("path/to/image1.jpg"); float width = 200f; float height = 150f; img1.scaleAbsolute(width, height); PdfContentByte cb = stamper.getOverContent(p); cb.addImage(img1, width, 0, 0, height, 36, 789 - height); // 调整坐标以适应页面布局 if (p == 2 || p == 4){ // 特定页码上放置额外一张图片 Image img2 = Image.getInstance("path/to/another_image.png"); img2.scalePercent(50); // 缩放到原大小的一半 cb.addImage(img2, null, false, 400, 0, 0, 400, // 宽高矩阵参数 36 + width + 20, 789 - height * 2// 新位置偏移量 ); } } } System.out.println("PDF with images has been created."); } } ``` 此代码片段说明了怎样通过指定不同的文件名和位置,在特定页面内插入不同尺寸的两张或多张图片[^2]。注意这里使用到了绝对定位方式 (`addImage`) 来精确控制每张图片的位置;对于更复杂的场景,则可能需要考虑其他方法如表单字段填充或自定义绘制逻辑[^3]。 此外,如果涉及到动态生成图表(例如 ECharts),则可以通过 PhantomJS 渲染 HTML/CSS/SVG 到静态 PNG/JPEG 图片后再按上述流程加入到 PDF 中[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值