第十七周_R-下载文件加水印

176 阅读2分钟

最近工作没什么任务,负责人说:你要不先看看 Java 下载怎么加水印吧。后续可能会用到。

我:1

pom

pom 必须给出来的。不然看的一头懵。

其中 spire.office.free 是公司开发的,而且源码经过处理的,被扰乱了。

<!--office 集合 -->
<dependency>
  <groupId>e-iceblue</groupId>
  <artifactId>spire.office.free</artifactId>
  <version>5.3.1</version>
</dependency>
    <!-- word 操作 -->
    <repositories>
        <repository>
            <id>com.e-iceblue</id>
            <name>e-iceblue</name>
            <url>https://repo.e-iceblue.cn/repository/maven-public/</url>
        </repository>
    </repositories>

代码

这里代码都是本地测试,所以直接保存为一个文件。实际开发应该是对流进行修改然后再下载。

公共图片方法

把下载内容整页大小作为背景图片,并写上水印文字。可控制

  • 字体大小、颜色
  • 字体透明体
  • 字体的间距
public static ByteArrayOutputStream createWaterMark(String content, int width, int height) throws IOException, FontFormatException {
    String[] contents = content.split(",");
    // 获取bufferedImage对象;整页大小的背景图
    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
    String fontType = "宋体";
    int fontStyle = Font.BOLD;
    int fontSize = 32;
    Font font = new Font(fontType, fontStyle, fontSize);
    //        font = font.deriveFont(15f);
    Graphics2D g2d = image.createGraphics(); // 获取Graphics2d对象
    image = g2d.getDeviceConfiguration().createCompatibleImage(width, height, Transparency.TRANSLUCENT);
    g2d.dispose();
    g2d = image.createGraphics();
    //设置字体颜色和透明度,最后一个参数为透明度
    g2d.setColor(new Color(128, 128, 128, 128));
    // 设置字体
    g2d.setStroke(new BasicStroke(1));
    // 设置字体类型  加粗 大小
    g2d.setFont(font);
    //设置倾斜度
    g2d.rotate(-0.5, (double) image.getWidth() / 2, (double) image.getHeight() / 2);
    // 获取其中最长的文字水印的大小
    int maxLen = 0;
    int maxHigh = 0;
    for (int i = 0; i < contents.length; i++) {
        content = contents[i];
        int fontlen = getWatermarkLength(content, g2d);
        if (fontlen >= maxLen) {
            maxLen = fontlen;
        }
        maxHigh = maxHigh + (i + 1) * fontSize + 10;
    }
    // 文字长度相对于图片宽度应该有多少行
    int line = width * 2 / maxLen;
    int co = height * 2 / maxHigh;

    int yz = 0;
    // 填充Y轴方向
    for (int a = 0; a < co; a++) {
        int t = 0;
        for (int j = 0; j < contents.length; j++) {
            content = contents[j];
            int y = (j + 1) * fontSize + 10 + t;

            // 文字叠加,自动换行叠加,注意符号
            int tempX = -width / 2;
            int tempY = -height / 2 + y + yz;
            // 单字符长度
            int tempCharLen = 0;
            // 单行字符总长度临时计算
            int tempLineLen = 0;
            StringBuffer sb = new StringBuffer();
            for (int i = 0; i < content.length(); i++) {
                char tempChar = content.charAt(i);
                tempCharLen = getCharLen(tempChar, g2d);
                tempLineLen += tempCharLen;

                // 和图片的长度进行对应的比较操作
                if (tempLineLen >= width) {
                    // 长度已经满一行,进行文字叠加
                    g2d.drawString(sb.toString(), tempX, tempY);
                    t = t + fontSize;
                    // 清空内容,重新追加
                    sb.delete(0, sb.length());
                    tempY += fontSize;
                    tempLineLen = 0;
                }
                // 追加字符
                sb.append(tempChar);
            }
            // 填充X轴
            for (int z = 0; z < line; z++) {
                // 最后叠加余下的文字
                g2d.drawString(sb.toString(), tempX, tempY);
                tempX = tempX + maxLen + XMOVE;
            }
            }
                yz = yz + maxHigh + YMOVE;
            }
                // 设置透明度
                g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
                // 释放对象
                g2d.dispose();
                ByteArrayOutputStream os = new ByteArrayOutputStream();
                ImageIO.write(image, "png", os);
                return os;
            }
public static int getWatermarkLength(String waterMarkContent, Graphics2D g) {
    return g.getFontMetrics(g.getFont()).charsWidth(waterMarkContent.toCharArray(), 0, waterMarkContent.length());
}

public static int getCharLen(char c, Graphics2D g) {
    return g.getFontMetrics(g.getFont()).charWidth(c);
}

pdf

public static void setPdfWatermarkBySpireOfficeFree(String input, String waterMarkName) throws IOException, FontFormatException {
    com.spire.pdf.PdfDocument pdf = new com.spire.pdf.PdfDocument();
    //加载示例文档
    pdf.loadFromStream(new FileInputStream(input));
    double height = pdf.getPages().get(0).getActualSize().getHeight();
    double width = pdf.getPages().get(0).getActualSize().getWidth();
    BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(createWaterMark(waterMarkName, (int) width, (int) height).toByteArray()));
    //获取第一页
    //遍历文档每一页,加载图片,并设置成平铺背景(水印)
    for (int i = 0; i < pdf.getPages().getCount(); i++) {
        PdfPageBase page = pdf.getPages().get(i);
        //设置背景图片
        page.setBackgroundImage(bufferedImage);
    }
    pdf.saveToFile("D:\myself\gitlab_self\keepon-java\keepon\think-in-basic\src\main\java\com\practice\thinkinbasic\下载文件加水印\testafter.pdf");
    //        //输出
    //        ByteArrayOutputStream dstStream = new ByteArrayOutputStream();
    //        pdf.saveToStream(dstStream, com.spire.pdf.FileFormat.PDF);
    //        byte[] bytes = dstStream.toByteArray();
    //        InputStream byteStream = new ByteArrayInputStream(bytes);
    //        dstStream.close();
    //
    //        return byteStream;

}

word

适配了 doc、docx

public static void setWordWatermark(String input, String waterName, int type) throws IOException, FontFormatException {
    String substring = input.substring(0, input.indexOf("."));
    String substring1 = input.substring(substring.length() + 1);

    InputStream stream = new FileInputStream(input);
    OutputStream outputStream = null;
    Document document = new Document();

    outputStream = new FileOutputStream("D:\myself\gitlab_self\keepon-java\keepon\think-in-basic\src\main\java\com\practice\thinkinbasic\下载文件加水印\testafter." + substring1);
    document.loadFromStream(stream, FileFormat.Auto);
    double height = document.getSections().get(0).getPageSetup().getPageSize().getHeight();
    double width = document.getSections().get(0).getPageSetup().getPageSize().getWidth();
    PictureWatermark picture = new PictureWatermark();
    picture.setPicture(new ByteArrayInputStream(createWaterMark(waterName, (int) width, (int) height).toByteArray()));
    //        picture.setScaling(20);
    picture.isWashout(false);
    //将图片设置成水印
    document.setWatermark(picture);
    document.saveToFile("D:\myself\gitlab_self\keepon-java\keepon\think-in-basic\src\main\java\com\practice\thinkinbasic\下载文件加水印\testafter." + substring1);

    outputStream.flush();
    outputStream.close();
}

excel

适配了 xls、xlsx

public static void setExcelWatermark(String input, String waterName, int type) throws IOException, FontFormatException {
    String substring = input.substring(0, input.indexOf("."));
    String substring1 = input.substring(substring.length() + 1);
    //加载Excel测试文档
    Workbook wb = new Workbook();
    wb.loadFromFile(input);
    int count=wb.getWorksheets().getCount();
    int width=180;
    int height=90;
    for (int i = 0; i < count; i++) {
        width= (int) wb.getWorksheets().get(i).getPageSetup().getPageWidth();
        height= (int) wb.getWorksheets().get(i).getPageSetup().getPageHeight();
        wb.getWorksheets().get(i).getPageSetup().setBackgoundImage(ImageIO.read(new ByteArrayInputStream(createWaterMark(waterName, width, height).toByteArray())));
        wb.getWorksheets().get(i).getPageSetup().setLeftHeader("&G");
    }
    wb.saveToFile("D:\myself\gitlab_self\keepon-java\keepon\think-in-basic\src\main\java\com\practice\thinkinbasic\下载文件加水印\testafter."+substring1);

    /**
* 旧的写法
*/
    //设置文本和字体大小
    //        Font font = new Font("仿宋", Font.PLAIN, 40);
    //        Font font = new Font("宋体", Font.PLAIN, 56);
    //        for (int i = 0; i < wb.getWorksheets().getCount(); i++) {
    //            Worksheet sheet = wb.getWorksheets().get(i);
    //            //调用DrawText() 方法插入图片
    //            BufferedImage imgWtrmrk = drawText(waterName, font, Color.GRAY, Color.WHITE, sheet.getPageSetup().getPageHeight(), sheet.getPageSetup().getPageWidth());
    //            //将图片设置为页眉
    //            sheet.getPageSetup().setLeftHeaderImage(imgWtrmrk);
    //            sheet.getPageSetup().setLeftHeader("&G");
    //            //将显示模式设置为Layout
    //            sheet.setViewMode(ViewMode.Layout);
    //        }
    //        //保存文档
    //        wb.saveToFile("D:\myself\gitlab_self\keepon-java\keepon\think-in-basic\src\main\java\com\practice\thinkinbasic\下载文件加水印\testafter.xls");
    //
}

ppt

适配了 ppt、pptx

public static void setPptWatermark(String input, String waterName, int type) throws Exception {
    String substring = input.substring(0, input.indexOf("."));
    String substring1 = input.substring(substring.length() + 1);

    Presentation presentation = new Presentation();
    presentation.loadFromFile(input, com.spire.presentation.FileFormat.AUTO);
    Dimension2D size = presentation.getSlideSize().getSize();
    int height = (int) size.getHeight();
    int width = (int) size.getWidth();
    //获取水印图片
    IImageData image = presentation.getImages().append(ImageIO.read(new ByteArrayInputStream(createWaterMark(waterName, width, height).toByteArray())));

    //获取幻灯片背景属性,设置图片填充
    SlideCollection slides = presentation.getSlides();
    for (int i = 0; i < slides.getCount(); i++) {
        SlideBackground background = presentation.getSlides().get(i).getSlideBackground();
        background.setType(BackgroundType.CUSTOM);
        background.getFill().setFillType(FillFormatType.PICTURE);
        background.getFill().getPictureFill().setFillType(PictureFillType.TILE);
        background.getFill().getPictureFill().getPicture().setEmbedImage(image);
    }
    presentation.saveToFile("D:\myself\gitlab_self\keepon-java\keepon\think-in-basic\src\main\java\com\practice\thinkinbasic\下载文件加水印\testafter."+substring1,com.spire.presentation.FileFormat.AUTO);
}

picture

   public static void setPicWatermark(String input, String waterMarkName) throws IOException, FontFormatException {

        String substring = input.substring(0, input.indexOf("."));
        String substring1 = input.substring(substring.length() + 1);

        String[] contents = waterMarkName.split(",");
        Image image = ImageIO.read(new FileInputStream(input));

        int width = image.getWidth(null);
        int height = image.getHeight(null);
        BufferedImage bufImg = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);

        String fontType = "宋体";
        int fontStyle = Font.BOLD;
        int fontSize = 32;
        Font font = new Font(fontType, fontStyle, fontSize);
//        font = font.deriveFont(15f);
        Graphics2D g2d = bufImg.createGraphics(); // 获取Graphics2d对象
        g2d.drawImage(image, 0, 0, width, height, null);
        g2d.setColor(new Color(128, 128, 128, 128));
        g2d.setFont(font);
        //设置倾斜度
        g2d.rotate(-0.5, (double) bufImg.getWidth() / 2, (double) bufImg.getHeight() / 2);
        // 获取其中最长的文字水印的大小
        int maxLen = 0;
        int maxHigh = 0;
        for (int i = 0; i < contents.length; i++) {
            waterMarkName = contents[i];
            int fontlen = getWatermarkLength(waterMarkName, g2d);
            if (fontlen >= maxLen) {
                maxLen = fontlen;
            }
            maxHigh = maxHigh + (i + 1) * fontSize + 10;
        }
        // 文字长度相对于图片宽度应该有多少行
        int line = width * 2 / maxLen;
        int co = height * 2 / maxHigh;

        int yz = 0;
        // 填充Y轴方向
        for (int a = 0; a < co; a++) {
            int t = 0;
            for (int j = 0; j < contents.length; j++) {
                waterMarkName = contents[j];
                int y = (j + 1) * fontSize + 10 + t;

                // 文字叠加,自动换行叠加,注意符号
                int tempX = -width / 2;
                int tempY = -height / 2 + y + yz;
                // 单字符长度
                int tempCharLen = 0;
                // 单行字符总长度临时计算
                int tempLineLen = 0;
                StringBuffer sb = new StringBuffer();
                for (int i = 0; i < waterMarkName.length(); i++) {
                    char tempChar = waterMarkName.charAt(i);
                    tempCharLen = getCharLen(tempChar, g2d);
                    tempLineLen += tempCharLen;

                    // 和图片的长度进行对应的比较操作
                    if (tempLineLen >= width) {
                        // 长度已经满一行,进行文字叠加
                        g2d.drawString(sb.toString(), tempX, tempY);
                        t = t + fontSize;
                        // 清空内容,重新追加
                        sb.delete(0, sb.length());
                        tempY += fontSize;
                        tempLineLen = 0;
                    }
                    // 追加字符
                    sb.append(tempChar);
                }
                // 填充X轴
                for (int z = 0; z < line; z++) {
                    // 最后叠加余下的文字
                    g2d.drawString(sb.toString(), tempX, tempY);
                    tempX = tempX + maxLen + XMOVE;
                }
            }
            yz = yz + maxHigh + YMOVE;
        }
        g2d.setComposite(AlphaComposite.getInstance(AlphaComposite.SRC_OVER));
        // 释放对象
        g2d.dispose();

        ImageIO.write(bufImg, substring1, new File("D:\myself\gitlab_self\keepon-java\keepon\think-in-basic\src\main\java\com\practice\thinkinbasic\下载文件加水印\testafter." + substring1));

    }

总结

基本思路就是:先获取文件流,再写图片设置到流中。最后一起保存。