附件文件增加水印

场景描述

附件上传时,文件中没有水印,下载前,加上水印。

实现思路

  1. 获取附件中文件的storeFileName,用于在服务中获取文件
  2. 调用自定义的服务,传入storeFileName参数,使用平台提供的StorageClient类下载文件
  3. 使用第三方工具给文件增加水印
  4. 返回文件流,浏览器预览或下载文件

实现步骤

1 前端js代码

1.1 从附件中获取storeFileName

附件上传后,存入数据库中的数据是一个JSON数组,代码如下。主要包括两项内容,一是存储文件名storeFileName,二是真实文件名realFileName。

[{
    "storeFileName":"anoy_CA30A885715000016616595C1A40134E外部应用导入说明.pdf",
    "realFileName":"外部应用导入说明.pdf"
}]

本例在表格中放附件组件和按钮组件,界面如下图所示

  • 表格中的第一列
    • 表格展示样式的附件组件,有预览和下载两个按钮,点击预览按钮触发附件组件的点击预览事件,点击下载按钮触发附件组件的下载事件
  • 表格中的第二列
    • 默认展示样式的附件组件,点击文件名,触发附件组件的点击预览事件
  • 表格中的第三列
    • 使用附件以外的按钮,实现预览和下载

1.2 调用自定义服务下载或预览文件

在附件组件的点击预览事件中,给event.data.file._previewUrl赋值为自定义服务的url,从而替代了附件组件默认的预览url,代码如下:

onUpload0Preview(event){
    let storeFileName = event.data.file.storeFileName;
    let realFileName = event.data.file.realFileName;
    let url = this.getServiceUrl("/main/fuwu/addwatermark?storeFileName="
        +storeFileName+"&realFileName="+realFileName+"&operateType=preview");
    event.data.file._previewUrl=url;
}

在附件组件的点击下载事件中,给event.data.file.downloadUrl赋值为自定义服务的url,从而替代了附件组件默认的下载url,代码如下:

onUpload0Download(event){
    let storeFileName = event.data.file.storeFileName;
    let realFileName = event.data.file.realFileName;
    let url = this.getServiceUrl("/main/fuwu/addwatermark?storeFileName="
        +storeFileName+"&realFileName="+realFileName+"&operateType=download");
    event.data.file.downloadUrl=url;
}

在按钮的点击事件中,获取表格当前行数据中的附件列数据,取出storeFileName和realFileName,在window.open中调用自定义服务的url,实现文件预览,代码如下:

onBtnPreviewClick(event){
    let files = event.context.$item.ffiles;
    files = JSON.parse(files);
    if(files && files.length>0){
        let storeFileName = files[0].storeFileName;
        let realFileName = files[0].realFileName;
        let url = this.getServiceUrl("/main/fuwu/addwatermark?storeFileName="
            +storeFileName+"&realFileName="+realFileName+"&operateType=preview");
        window.open(url);
    }
}

在按钮的点击事件中,获取表格当前行数据中的附件列数据,取出storeFileName和realFileName,在window.open中调用自定义服务的url,实现文件下载,代码如下:

onBtnDownloaadClick(event){
    let files = event.context.$item.ffiles;
    files = JSON.parse(files);
    if(files && files.length>0){
        let storeFileName = files[0].storeFileName;
        let realFileName = files[0].realFileName;
        let url = this.getServiceUrl("/main/fuwu/addwatermark?storeFileName="
            +storeFileName+"&realFileName="+realFileName+"&operateType=download");
        window.open(url);
    }
}

2 后端java代码

自定义服务接收三个参数

  • storeFileName:用于获取文件
  • realFileName:用于返回文件名
  • operateType:用于设置响应头,是预览还是下载

另外,这个服务需要返回文件流,平台的服务不能返回,因此通过自定义controller实现。

2.1 添加controller

在src/main/java/main目录下增加controller目录,在该目录下增加controller文件

controller文件的代码如下:

package main.controller;


import java.io.IOException;
import java.io.InputStream;

import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.justep.util.SpringWebUtil;

import main.service.FuwuUserService;

@RestController
public class FuwuUserController {
    @Autowired
    private FuwuUserService service;

    @GetMapping("/main/fuwu/addwatermark")
    public void addWatermark(@RequestParam String storeFileName,@RequestParam String realFileName,@RequestParam String operateType) throws Exception {
        HttpServletResponse response = SpringWebUtil.getResponse();

        //调用service获取加了水印的文件流
        InputStream fis = service.addWatermark(storeFileName);
        try {
            response.reset();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/octet-stream");
            //参数为attachment代表下载,参数为inline代表预览,预览前提是文件支持预览的,并且contentType不为application/octet-stream
            //根据operateType参数值,确定是下载还是预览
            if("download".equals(operateType)) {
                response.setHeader("Content-Disposition","attachment;filename=" + new String(realFileName.getBytes("utf-8"), "ISO-8859-1"));
                response.setContentType("application/octet-stream");

            }else {
                response.setHeader("Content-Disposition","inline;filename=" + new String(realFileName.getBytes("utf-8"), "ISO-8859-1"));
                response.setContentType("application/pdf");

            }

            byte[] bytes = new byte[1024];
            int len;
            while ((len = fis.read(bytes)) != -1) {
                response.getOutputStream().write(bytes, 0, len);
            }
            response.flushBuffer();
            fis.close();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}

2.2 添加service

在src/main/java/main目录下增加service目录,在该目录下增加service文件

在service文件中添加增加水印的方法

  • 用storeFileName获取文件流
  • 使用第三方工具给pdf文件的第一页增加水印(代码来自于网络)
  • 返回加了水印的文件流

增加水印方法的代码如下:

//增加水印
public InputStream addWatermark(String storeFileName) throws Exception {
    //下载文档
    StorageApi instance = StorageClient.getInstance();
    InputStream is = instance.getObject(storeFileName, storeFileName, storeFileName);

    PdfDocument pdf = new PdfDocument();
    //加载文档
    pdf.loadFromStream(is);
    //获取 PDF 的第一页
    PdfPageBase page = pdf.getPages().get(0);
    //插入水印
    insertWatermark(page, "abcd");
    //保存文档
    ByteArrayOutputStream  os = new ByteArrayOutputStream();
    pdf.saveToStream(os);
    byte[] buffer = os.toByteArray();
    InputStream sbs = new ByteArrayInputStream(buffer);
    pdf.close();

    //返回已加水印的文件流
    return sbs;
}

static void insertWatermark(PdfPageBase page, String watermark) {
    Dimension2D dimension2D = new Dimension();
    dimension2D.setSize(page.getCanvas().getClientSize().getWidth() / 2, page.getCanvas().getClientSize().getHeight() / 3);
    PdfTilingBrush brush = new PdfTilingBrush(dimension2D);
    brush.getGraphics().setTransparency(0.3F);
    brush.getGraphics().save();
    brush.getGraphics().translateTransform((float) brush.getSize().getWidth() / 2, (float) brush.getSize().getHeight() / 2);
    brush.getGraphics().rotateTransform(-45);
    PdfTrueTypeFont font1 = new PdfTrueTypeFont(new Font("微软雅黑", Font.PLAIN, 14), true);
    brush.getGraphics().drawString(watermark, font1, PdfBrushes.getViolet(), 0, 0, new PdfStringFormat(PdfTextAlignment.Center));
    brush.getGraphics().restore();
    brush.getGraphics().setTransparency(1);
    Rectangle2D loRect = new Rectangle2D.Float();
    loRect.setFrame(new Point2D.Float(0, 0), page.getCanvas().getClientSize());
    page.getCanvas().drawRectangle(brush, loRect);
}

service文件引用的包如下:

package main.service;

import java.awt.Dimension;
import java.awt.Font;
import java.awt.geom.Dimension2D;
import java.awt.geom.Point2D;
import java.awt.geom.Rectangle2D;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import org.springframework.stereotype.Service;

import com.justep.clients.StorageClient;
import com.justep.clients.api.StorageApi;
import com.spire.pdf.PdfDocument;
import com.spire.pdf.PdfPageBase;
import com.spire.pdf.graphics.PdfBrushes;
import com.spire.pdf.graphics.PdfFont;
import com.spire.pdf.graphics.PdfFontFamily;
import com.spire.pdf.graphics.PdfStringFormat;
import com.spire.pdf.graphics.PdfTextAlignment;
import com.spire.pdf.graphics.PdfTilingBrush;
import com.spire.pdf.graphics.PdfTrueTypeFont;

2.3 将第三方jar复制到tomcat/ROOT下

本例中使用的spire.pdf-3.4.2.jar放到tomcat/ROOT目录下才能正常使用,model\service\main\lib目录下的jar保留,用于服务编译。

在本地ide中,将jar复制到newdao-ide-windows\eclipse-workspace-template\ROOT\WEB-INF\lib目录下即可。

在云ide中

  • 将jar复制到model\service\main\deploy目录下
  • 在model\service\main\deploy目录下新建install.sh文件,内容如下,含义是将当前目录下的jar复制到$JUSTEP_HOME/../tomcat/webapps-system/ROOT/WEB-INF/lib目录下
  • 用system登录控制台,进入资源管理-池管理-开发池,找到当前ide的池,进入详情,进入tomcat终端,执行/usr/local/x5/model/service/main/deploy/install.sh,将jar复制到/usr/local/tomcat/webapps-system/ROOT/WEB-INF/lib目录下
  • Tomcat下面有jar就可以运行pdf加水印
  • install.sh的作用是发布后,应用安装或更新时会执行,可将jar复制到tomcat目录下

install.sh文件内容如下

#!/bin/bash
startDir=$(dirname $(readlink -f "$0"))
cd $startDir
cp spire.pdf-3.4.2.jar $JUSTEP_HOME/../tomcat/webapps-system/ROOT/WEB-INF/lib

model\service\main\deploy目录下的内容如下图所示

2.4 关于字体

平台提供了六种字体,分别是微软雅黑、宋体、新宋体、仿宋、黑体和楷体。字体文件放在/usr/share/fonts/chinese/TrueType目录下。

如需上传新字体,使用2.3里面介绍的,在sh文件中复制文件cp的方法,将字体文件复制到/usr/share/fonts/chinese/TrueType目录下即可。

results matching ""

    No results matching ""

    results matching ""

      No results matching ""