Java根据前端传回的图片生成pdf并且加密码和水印

 更新时间:2025年01月23日 09:01:58   作者:小七蒙恩  
这篇文章主要为大家详细介绍了java如何根据前端传回的png图片数组,后端加水印加密码生成pdf并返回给前端,感兴趣的小伙伴可以参考一下

场景

当前需求,前端通过html2canvas将页面报表生成图片下载,可以仍然不满意。

需要java后端将前端传过来的图片生成pdf,并且加密码加水印。

重点

pdf使用A4大小,但是要考虑。根据A4宽高缩放图片后,图片仍然大于A4长度,此时要对图片进行裁剪(2页,3页…)

maven依赖

<!-- pdf文件水印添加 -->
<dependency>
    <groupId>com.itextpdf</groupId>
    <artifactId>itext7-core</artifactId>
    <version>7.1.4</version>
    <type>pom</type>
</dependency>

controller

    @PostMapping("/addMarkAndPasswordPdf")
    @ApiOperation(value = "文件处理-增加水印及密码--入参为文件", notes = "")
    public void addMarkAndPasswordPdf(@RequestParam("fileStream") MultipartFile[] fileStreams,@RequestParam("filePdfName")String filePdfName,  HttpServletRequest request, HttpServletResponse response) {

        Calendar calendar = Calendar.getInstance();
        String date = calendar.get(Calendar.YEAR) + "-" + (calendar.get(Calendar.MONTH) + 1);

        SysUserEntity uc = (SysUserEntity) request.getAttribute("UC");

        SysUserEntity uc1 = userService.getUserByCode(uc.getUserCode());



        fileProcessService.fileProcessPdf(fileStreams,filePdfName,uc1,response);
    }

service

  @Override
    public void fileProcessPdf(MultipartFile[] imageFiles,String filePdfName, SysUserEntity uc, HttpServletResponse response) {
        response.setHeader("Content-disposition", "attachment;filename=" + filePdfName);
        // 直接用浏览器或者用postman
        response.setContentType("application/pdf");
        response.setCharacterEncoding("utf-8");
        try {
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            // 创建PDF文档 加密PDF文档
            PdfWriter writer = new PdfWriter(byteArrayOutputStream,new WriterProperties().setStandardEncryption(
                    // 用户密码
                    uc.getPassword().getBytes(),
                    // 所有者密码
                    uc.getPassword().getBytes(),
                    // 允许的权限
                    EncryptionConstants.ALLOW_PRINTING | EncryptionConstants.ALLOW_COPY,
                    // 加密标准
                    EncryptionConstants.STANDARD_ENCRYPTION_128
            ));
            PdfDocument pdfDoc = new PdfDocument(writer);
            Document document = new Document(pdfDoc);
            // 读取原始图片.按照A4拆分图片,放到pdf
            for(MultipartFile imageFile: imageFiles){
                BufferedImage originalImage = ImageIO.read(imageFile.getInputStream());
                float maxHeight =  (PageSize.A4.getHeight()/PageSize.A4.getWidth())*originalImage.getWidth();
                ArrayList<BufferedImage> cropImageList = cropImageByMaxHeight(originalImage, (int) maxHeight);
                for (BufferedImage bufferedImage : cropImageList) {
                    // 添加图片
                    PdfPage page = pdfDoc.addNewPage();
                    ByteArrayOutputStream ImageOutputStream = new ByteArrayOutputStream();
                    ImageIO.write(bufferedImage, "png", ImageOutputStream);
                    ImageData imageData = ImageDataFactory.create(ImageOutputStream.toByteArray());
                    com.itextpdf.layout.element.Image image = new com.itextpdf.layout.element.Image(imageData);
                    image.setHorizontalAlignment(HorizontalAlignment.CENTER);
                    document.add(image);
                    ImageOutputStream.close();
                    // 循环为页设置水印
                    setPageWatermark(page, pdfDoc,uc.getCname() + ", " + uc.getDeptTwo(),140);
                }
            }

            // 关闭文档以不再写入内容
            document.close();
            pdfDoc.close();
            writer.close();
            // 将PDF写入响应输出流
            response.getOutputStream().write(byteArrayOutputStream.toByteArray());
            response.getOutputStream().flush();
            byteArrayOutputStream.close();
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
        }
    }

    /***
     * 为PDF页绘画水印
     * @param pdfPage PDF页对象
     * @param msg 水印信息
     * @param interval 水印间隔
     * @throws IOException 这里的异常是无法获取字体异常
     */
    public static void setPageWatermark(PdfPage pdfPage,PdfDocument pdfDoc, String msg, int interval) throws IOException {
        // 通过PDF页来构建画布
        PdfCanvas pdfCanvas = new PdfCanvas(pdfPage);
        // 中文显示字体
//        PdfFont font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H");
        float width = pdfPage.getPageSize().getWidth();
        float height = pdfPage.getPageSize().getHeight();
        // 开始绘画水印
        for (int x = 0; x < pdfPage.getPageSize().getWidth(); x += interval) {
            for (int y = 0; y < pdfPage.getPageSize().getHeight(); y += interval) {
                Canvas canvas = new Canvas(pdfCanvas, pdfDoc, new Rectangle(0, 0, width, height))
                        // 颜色和透明度
                        .setFontColor(ColorConstants.GRAY, .2f)
                        // 文字样式
//                        .setFont(font)
                        // 字体大小(具体可以改)
                        .setFontSize(20)
                        .showTextAligned(msg, x, y, TextAlignment.CENTER,
                                VerticalAlignment.MIDDLE, 19.5f);
                canvas.close();
            }
        }
        // 释放画布。使用完画布后,请使用此方法。
        pdfCanvas.release();
    }



    /**
     * 将图片进行裁剪
     *
     * @param originalImage
     * @param maxHeight
     * @return
     */
    public static ArrayList<BufferedImage> cropImageByMaxHeight(BufferedImage originalImage, int maxHeight) {
        ArrayList<BufferedImage> croppedImages = new ArrayList<>();
        int originalHeight = originalImage.getHeight();
        int numImages = originalHeight / maxHeight;
        int remainder = originalHeight % maxHeight;

        for (int i = 0; i < numImages; i++) {
            int y = i * maxHeight;
            BufferedImage croppedImage = originalImage.getSubimage(0, y, originalImage.getWidth(), maxHeight);
            croppedImages.add(croppedImage);
        }

        // 处理剩余高度(如有)
        if (remainder > 0) {
            int y = numImages * maxHeight;
            BufferedImage croppedImage = originalImage.getSubimage(0, y, originalImage.getWidth(), remainder);
            croppedImages.add(croppedImage);
        }

        return croppedImages;
    }

成果

以上就是Java根据前端传回的图片生成pdf并且加密码和水印的详细内容,更多关于Java图片生成pdf的资料请关注脚本之家其它相关文章!

相关文章

  • Java格式化日期和时间三种方法

    Java格式化日期和时间三种方法

    这篇文章主要给大家介绍了关于Java格式化日期和时间三种方法的相关资料,最近遇到很多在Java里获取当前时间的问题,文中通过图文以及实例代码介绍的非常详细,需要的朋友可以参考下
    2023-07-07
  • 基于Spring AMQP实现消息队列的示例代码

    基于Spring AMQP实现消息队列的示例代码

    Spring AMQP作为Spring框架的一部分,是一套用于支持高级消息队列协议(AMQP)的工具,AMQP是一种强大的消息协议,旨在支持可靠的消息传递,本文给大家介绍了如何基于Spring AMQP实现消息队列,需要的朋友可以参考下
    2024-03-03
  • Java初始化块及执行过程解析

    Java初始化块及执行过程解析

    这篇文章主要介绍了Java初始化块及执行过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • SpringBootAdmin+actuator实现服务监控

    SpringBootAdmin+actuator实现服务监控

    这篇文章主要为大家详细介绍了SpringBootAdmin+actuator实现服务监控,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • java实现图片分割指定大小

    java实现图片分割指定大小

    这篇文章主要为大家详细介绍了java实现图片分割指定大小,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • Java 线程池详解

    Java 线程池详解

    本文给大家总结了java中的线程池的相关问题,非常的详细也很实用,有需要的小伙伴可以参考下。
    2016-03-03
  • 利用logback filter过滤某个类 屏蔽某个类

    利用logback filter过滤某个类 屏蔽某个类

    这篇文章主要介绍了利用logback filter过滤某个类 屏蔽某个类的操作,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2021-07-07
  • 关于消息中间件RocketMQ的基本概念及功能

    关于消息中间件RocketMQ的基本概念及功能

    这篇文章主要介绍了关于消息中间件RocketMQ的基本概念及功能,RocketMQ作为一款纯java、分布式、队列模型的开源消息中间件,支持事务消息、顺序消息、批量消息、定时消息、消息回溯等,需要的朋友可以参考下
    2023-05-05
  • 解析Java编程中设计模式的开闭原则的运用

    解析Java编程中设计模式的开闭原则的运用

    这篇文章主要介绍了解析Java编程中设计模式的开闭原则的运用,开闭原则多应用于Java程序的扩展开发方面,需要的朋友可以参考下
    2016-02-02
  • SpringBoot集成Knife4j实现接口文档和参数校验

    SpringBoot集成Knife4j实现接口文档和参数校验

    Knife4j 是国人开发的接口文档增强工具,底层基于 OpenAPI 规范,但提供了比原生 Swagger UI 更美观、更贴合国内开发者习惯的中文界面,本文就给大家介绍了SpringBoot集成Knife4j实现接口文档和参数校操作步骤,需要的朋友可以参考下
    2026-03-03

最新评论