You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在文档管理系统中实现PDF设备/用户信息水印功能?

实现文档管理系统中的两类PDF水印功能

一、基于设备信息的PDF水印实现

  • 获取设备信息:根据操作场景获取对应标识:
    • 后端服务侧:可获取服务器的主机名、IP地址(注意MAC地址获取可能受系统权限限制)
    • 客户端触发场景(如上传时添加):通过前端JS获取浏览器UA,再结合后端接口获取客户端IP
  • PDF水印添加逻辑:选用成熟的PDF处理库,以下是Python(PyPDF2+ReportLab)的实现示例:
    from PyPDF2 import PdfReader, PdfWriter
    from reportlab.pdfgen import canvas
    from io import BytesIO
    import datetime
    
    def add_device_watermark(input_pdf, output_pdf, device_info):
        # 生成水印PDF
        packet = BytesIO()
        can = canvas.Canvas(packet)
        # 设置水印样式:浅灰、斜体、半透明
        can.setFillColorRGB(0.7, 0.7, 0.7, alpha=0.3)
        can.setFont("Helvetica-Oblique", 32)
        can.rotate(45)
        # 拼接设备信息,可加入时间戳
        watermark_content = f"{device_info} | {datetime.datetime.now().strftime('%Y-%m-%d')}"
        can.drawString(220, 300, watermark_content)
        can.save()
    
        # 合并水印与原PDF
        packet.seek(0)
        watermark_pdf = PdfReader(packet)
        original_pdf = PdfReader(input_pdf)
        writer = PdfWriter()
    
        for page in original_pdf.pages:
            page.merge_page(watermark_pdf.pages[0])
            writer.add_page(page)
    
        with open(output_pdf, "wb") as out_file:
            writer.write(out_file)
    
  • 触发时机:可设置为文档上传至系统时自动执行,或提供管理员批量添加入口。

二、特定用户下载时自动添加用户信息水印

  • 获取用户信息:从系统会话中提取用户名、用户ID、下载时间等非敏感信息,严格避免在水印中暴露手机号、邮箱等隐私数据
  • 动态生成带水印的PDF:在用户发起下载请求时,后端实时处理原PDF,添加水印后直接返回给用户,不修改系统存储的原文件。以下是Java(iText 7)的实现示例:
    import com.itextpdf.kernel.colors.Color;
    import com.itextpdf.kernel.pdf.PdfDocument;
    import com.itextpdf.kernel.pdf.PdfReader;
    import com.itextpdf.kernel.pdf.PdfWriter;
    import com.itextpdf.layout.Document;
    import com.itextpdf.layout.element.Paragraph;
    import com.itextpdf.layout.property.TextAlignment;
    import com.itextpdf.layout.property.VerticalAlignment;
    
    import javax.servlet.http.HttpServletResponse;
    import java.io.IOException;
    import java.time.LocalDateTime;
    import java.time.format.DateTimeFormatter;
    
    public void generateWatermarkedPdfForUser(String originalPdfPath, HttpServletResponse response, UserSession userSession) throws IOException {
        // 设置响应头,指定下载类型
        response.setContentType("application/pdf");
        response.setHeader("Content-Disposition", "attachment; filename=\"document_" + userSession.getUserId() + ".pdf\"");
    
        // 读取原PDF并绑定响应输出流
        PdfReader reader = new PdfReader(originalPdfPath);
        PdfWriter writer = new PdfWriter(response.getOutputStream());
        PdfDocument pdfDoc = new PdfDocument(reader, writer);
        Document document = new Document(pdfDoc);
    
        // 构造水印内容
        String watermarkText = String.format("下载用户:%s | 用户ID:%d | 下载时间:%s",
                userSession.getUsername(),
                userSession.getUserId(),
                LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
    
        // 为每一页添加水印
        int totalPages = pdfDoc.getNumberOfPages();
        for (int pageNum = 1; pageNum <= totalPages; pageNum++) {
            document.showTextAligned(
                    new Paragraph(watermarkText)
                            .setFontColor(Color.LIGHT_GRAY)
                            .setFontSize(26),
                    pdfDoc.getPage(pageNum).getPageSize().getWidth() / 2,
                    pdfDoc.getPage(pageNum).getPageSize().getHeight() / 2,
                    pageNum,
                    TextAlignment.CENTER,
                    VerticalAlignment.MIDDLE,
                    45);
        }
    
        // 关闭资源
        document.close();
        reader.close();
    }
    
  • 关键注意事项:
    • 水印透明度建议设置在0.2-0.4之间,避免遮挡文档内容
    • 优先选择斜向居中的水印位置,平衡辨识度与可读性
    • 确保下载接口的权限校验,只有授权用户才能触发水印生成逻辑

内容的提问来源于stack exchange,提问作者Kanchana M

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.18 21:10:38