[Java]Spring/SpringBoot利用itextpdf将JPG/PNG/TIF等输出为PDF(解决TIF多页合并问题)

2021-01-20 475点热度 3人点赞 0条评论

需求是浏览器里直接将服务器上的图片文件(JPG,PNG,TIF)输出PDF, TIF还可能是多页的,这里需要把TIF合并,项目是用的Spring/SpringBoot

首先引入itextpdf依赖,编辑pom.xml,增加如下dependency

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

配置Controller,输出的格式是PDF,这样浏览器能认出是PDF文档

@Controller
@RequestMapping("/api")
public class ApiController {
    @RequestMapping(value = "/drawings_{no}.pdf", method = RequestMethod.GET)
    public String drawings(@PathVariable("no") String no, HttpServletRequest request, HttpServletResponse response) {
        try {
            //processDrawings就是处理输出PDF的,我们在下一个方法介绍
            byte[] contents = processDrawings(no);
            String filename = "drawings_" + no + ".pdf";

            response.setContentType("application/pdf");
            //比较关键的是Content-Disposition是inline而不是attachment,这样提示浏览器来显示文档而不是下载
            response.setHeader("Content-Disposition", "inline; fileName=" + filename);
            response.setContentLength(contents.length);

            response.getOutputStream().write(contents);
            response.getOutputStream().flush();
        } catch (Exception e) {
            //request.setAttribute("message", "无法输出图号为: " + no + " 的图纸" + (e.getMessage() == null ? "" : ("<br/>" + e.getMessage())));
            //return "forward:/message";
            throw new HttpClientErrorException(HttpStatus.NOT_FOUND);
        }
        return null;
    }
}

下面给出itextpdf处理图像文件输出为PDF的方法,说明写到注释里了

@Override
    public byte[] processDrawings(String no) throws Exception {
        String keywords = no.length() > 8 ? no.substring(0, 8) : no;
        String[] allowedExts = new String[]{".jpg", ".jpeg", ".tif", ".tiff"};
        List<File> foundFiles;
        //根据业务逻辑的规则,找出需要合并的图像文件,或者得到自己业务生成的图片
        try (Stream<Path> paths = Files.find(Paths.get("/path/to/image_folder"),
                10,
                (filePath, fileAttr) -> {
                    if (fileAttr.isRegularFile()) {
                        String name = filePath.getFileName().toString();
                        if (isContainsAllowedExts(name, allowedExts)) {
                            return name.startsWith(keywords);
                        }
                    }
                    return false;
                }, FileVisitOption.FOLLOW_LINKS)) {
            foundFiles = paths.map(Path::toFile).sorted(Comparator.comparing(File::getName)).collect(Collectors.toList());
        }

        if (foundFiles.size() == 0) {//找不到
            throw new FileNotFoundException("找不到图纸文件");
        }
        

        Document document = new Document();
        document.setMargins(0, 0, 0, 0);

        //这里我需要直接输出到ByteArrayOutputStream,如果你要把图片输出到PDF文件保存,可以使用FileOutputStream
        ByteArrayOutputStream bos = new ByteArrayOutputStream();

        PdfWriter.getInstance(document, bos);
        document.open();
        for (File file1 : foundFiles) {
            String fileName = file1.getName().toLowerCase();
            if (fileName.endsWith(".tif") || fileName.endsWith(".tiff")) {
                //如果是TIF图片,可能是多页,需要解析出每一页,输出到PDF里去
                RandomAccessFileOrArray tifFile = new RandomAccessFileOrArray(file1.getAbsolutePath());
                int numberOfPages = TiffImage.getNumberOfPages(tifFile);
                for (int i = 1; i <= numberOfPages; i++) {
                    Image image = TiffImage.getTiffImage(tifFile, i);
                    document.setPageSize(new Rectangle(image.getWidth(), image.getHeight()));

                    document.newPage();
                    document.add(image);
                }

            } else {//其他图像文件,就直接写入到PDF里去
                Image image = Image.getInstance(file1.getAbsolutePath());
                document.setPageSize(new Rectangle(image.getWidth(), image.getHeight()));

                document.newPage();
                document.add(image);
            }
        }
        document.close();

        return bos.toByteArray();

好了,现在启动程序,浏览器里输入 http://localhost:8080/api/drawings_123.pdf 就能直接看到PDF了

如何将多个PDF合并为一个,请移步另一篇文章:https://blog.terrynow.com/2021/01/22/java-itext-pdf-merge/

admin

这个人很懒,什么都没留下

文章评论

*

code