【文件操作专题】java 实现多张图片合成PDF

本篇文章分析如何将多张图片合成一个pdf文件,留下此篇文章,方便以后查阅,从网上找了很多案例,最后找了itextpdf这个比较好,最重要的是,要最下缩放比例,由于我们使用的图片大小都不一样的规格,直接放到pdf会失真,这样就不是很好了。
在这里插入图片描述

操作步骤

首先肯定是pom依赖

<!-- https://mvnrepository.com/artifact/org.apache.pdfbox/pdfbox -->
        <dependency>
            <groupId>org.apache.pdfbox</groupId>
            <artifactId>pdfbox</artifactId>
            <version>2.0.9</version>
        </dependency>
  <!-- https://mvnrepository.com/artifact/com.itextpdf/itextpdf -->
  <dependency>
      <groupId>com.itextpdf</groupId>
      <artifactId>itextpdf</artifactId>
      <version>5.5.13</version>
  </dependency>

转换pdf工具类

考虑到了缩放比例的问题,还有pdf的大小,每页的pdf高度的适配。

import com.itextpdf.text.Document;
import com.itextpdf.text.Image;
import com.itextpdf.text.Rectangle;
import com.itextpdf.text.pdf.PdfWriter;
import lombok.extern.slf4j.Slf4j;

import java.io.File;
import java.io.FileOutputStream;


/**
 * 图片转pdf工具类
 *
 * @author Administrator
 */
@Slf4j
public class Img2PdfUtil {


    /**
     * @param imageFiles 需要转换的图片File类Array,按array的顺序合成图片
     */
    public static File imagesToPdf(File[] imageFiles) throws Exception {

        log.info("进入图片合成PDF工具方法");
        File tempFile = File.createTempFile("tmpFile", ".pdf");
        // 第一步:创建一个document对象。
        Document document = new Document();
        document.setMargins(0, 0, 0, 0);
        // 第二步:
        // 创建一个PdfWriter实例,
        PdfWriter.getInstance(document, new FileOutputStream(tempFile));
        // 第三步:打开文档。
        document.open();
        // 第四步:在文档中增加图片。
        int len = imageFiles.length;

        for (int i = 0; i < len; i++) {
            if (imageFiles[i].getName().toLowerCase().endsWith(".bmp")
                    || imageFiles[i].getName().toLowerCase().endsWith(".jpg")
                    || imageFiles[i].getName().toLowerCase().endsWith(".jpeg")
                    || imageFiles[i].getName().toLowerCase().endsWith(".gif")
                    || imageFiles[i].getName().toLowerCase().endsWith(".png")) {
                String temp = imageFiles[i].getAbsolutePath();
                log.info("图片路径:" + temp);
                Image img = Image.getInstance(temp);
//                img.scaleAbsolute(597, 844);// 直接设定显示尺寸
                int percent = getPercent(img.getHeight(), img.getWidth());
                System.out.println("--" + percent);
                //设置图片居中显示
                img.setAlignment(Image.ALIGN_CENTER);
                img.setAlignment(Image.ALIGN_MIDDLE);
                //按百分比显示图片的比例
                img.scalePercent(percent);//表示是原来图像的比例;
                // 根据图片大小设置页面,一定要先设置页面,再newPage(),否则无效
                //document.setPageSize(new Rectangle(img.getWidth(), img.getHeight()));
//                document.setPageSize(new Rectangle(597, 844));
                document.setPageSize(getRectangle(img.getHeight(), img.getWidth()));
                document.newPage();
                document.add(img);
            }
        }
        // 第五步:关闭文档。
        document.close();
        log.info("图片合成PDF完成");
        return tempFile;
    }

    public static Rectangle getRectangle(float h, float w) {
        int p = 0;
        float p2 = 0.0f;
        if (h > w) {
            p2 = 841 / h * 100;
            return new Rectangle(595, 841, Math.round(p2));
        } else {
            p2 = 595 / w * 100;
            float v = (float) (595 / w * 1.0);
            return new Rectangle(595, h * v, Math.round(p2));
        }
    }

    /**
     * 第一种解决方案
     * 在不改变图片形状的同时,判断,如果h>w,则按h压缩,否则在w>h或w=h的情况下,按宽度压缩
     *
     * @param h
     * @param w
     * @return
     */

    public static int getPercent(float h, float w) {
        int p = 0;
        float p2 = 0.0f;
        if (h > w) {
            p2 = 841 / h * 100;
        } else {
            p2 = 595 / w * 100;
        }
        p = Math.round(p2);
        return p;
    }
}

下载工具方法

就是pdf的字节流输出到浏览器

private void download(HttpServletResponse response, File file) {
        HttpHeaders headers = new HttpHeaders();
        headers.add("Cache-Control", "no-cache, no-store, must-revalidate");
        headers.add("Content-Disposition", String.format("attachment; filename=\"%s\"", "test.pdf"));
        headers.add("Pragma", "no-cache");
        headers.add("Expires", "0");

        response.setContentType("application/force-download");
        response.setHeader("Content-Disposition", "attachment;fileName=" + "test.pdf");

        byte[] buffer = new byte[1024];
        FileInputStream fis = null; //文件输入流
        BufferedInputStream bis = null;

        OutputStream os; //输出流
        try {
            os = response.getOutputStream();
            fis = new FileInputStream(file);
            bis = new BufferedInputStream(fis);
            int i = bis.read(buffer);
            while (i != -1) {
                os.write(buffer);
                i = bis.read(buffer);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            bis.close();
            fis.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

测试接口

@GetMapping("testImgToPdf")
    public void testImgToPdf(HttpServletResponse response) throws Exception {
        List<String> urls = Arrays.asList("http://pic.netbian.com/uploads/allimg/180826/113958-153525479855be.jpg",
                "http://pic.netbian.com/uploads/allimg/190415/214606-15553359663cd8.jpg");
        List<File> files = new ArrayList<>();
        urls.forEach(item -> {
            InputStream inputStream = returnBitMap(item);
            try {
                File file = inputStream2File(inputStream, ".jpg");
                files.add(file);
            } catch (IOException e) {
                log.error(e.getMessage(), e);
            }
        });
        File file = Img2PdfUtil.imagesToPdf(files.toArray(new File[files.size()]));
        download(response, file);
    }

访问接口可以看到pdf。

在这里插入图片描述

总结

  • 以上的方式还有很多不好的地方,由于笔者技术欠缺,一定会继续调研更好的方法,如果有好的方案,可以留下评论。

  • 本人QQ: 476688386

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值