如何在文档管理系统中实现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
相关产品推荐
相关产品推荐

