手把手零门槛搭建支持下载加水印的轻量档案系统
前期准备
1. 安装Docker和Docker Compose
我们用Docker快速搭建环境,避免繁琐的依赖配置。
- Windows/macOS用户:直接下载Docker Desktop安装包,地址为https://www.docker.com/products/docker-desktop/,安装后启动并确保右下角托盘Docker图标显示为绿色。
- Linux(Ubuntu/Debian)用户:依次执行以下命令:
2. 准备项目目录
在任意位置创建项目文件夹,命名为watermark-archive,然后进入该文件夹,后续操作都在此目录下进行。
- Windows/macOS用户:右键新建文件夹,重命名后双击进入。
- Linux用户:执行命令
mkdir watermark-archive && cd watermark-archive。
核心配置文件
1. 配置docker-compose.yml
该文件定义我们的两个核心服务:MinIO(轻量对象存储,作为档案存储载体)和Watermark-Service(我们自己写的轻量下载水印添加服务)。在项目目录下新建docker-compose.yml,复制以下内容:
2. 创建Python代码目录和文件
在项目目录下新建app子文件夹,然后在app中创建3个文件:requirements.txt(依赖包列表)、app.py(核心业务逻辑)、config.py(参数配置)。
requirements.txt
复制以下内容:
``` minio==7.2.10 flask==3.0.3 Pillow==10.3.0 python-dotenv==1.0.1 ```config.py
复制以下内容,注意替换MINIO_ROOT_PASSWORD为你在docker-compose.yml中设置的密码:
app.py

复制以下内容,这是完整的带水印下载服务代码:
```python from flask import Flask, send_file, request, abort from minio import Minio from minio.error import S3Error from PIL import Image, ImageDraw, ImageFont from io import BytesIO import os from config import app = Flask(__name__) 初始化MinIO客户端 minio_client = Minio( MINIO_ENDPOINT, access_key=MINIO_ACCESS_KEY, secret_key=MINIO_SECRET_KEY, secure=MINIO_SECURE ) 创建默认存储桶(如果不存在) def create_bucket_if_not_exists(): try: if not minio_client.bucket_exists(MINIO_BUCKET_NAME): minio_client.make_bucket(MINIO_BUCKET_NAME) print(f"存储桶 {MINIO_BUCKET_NAME} 创建成功") except S3Error as e: print(f"存储桶操作失败: {e}") 添加图片水印 def add_image_watermark(image_data, username): img = Image.open(BytesIO(image_data)).convert('RGBA') width, height = img.size 准备水印文本 text = f"{WATERMARK_TEXT}\n用户: {username}\n时间: {request.remote_addr}" if username else WATERMARK_TEXT 尝试加载系统字体,失败则用默认 try: if os.name == 'nt': font = ImageFont.truetype('C:/Windows/Fonts/simhei.ttf', WATERMARK_FONT_SIZE) else: font = ImageFont.truetype('/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf', WATERMARK_FONT_SIZE) except IOError: font = ImageFont.load_default() 创建水印图层 watermark_layer = Image.new('RGBA', img.size, (255, 255, 255, 0)) draw = ImageDraw.Draw(watermark_layer) 计算文本尺寸(兼容Pillow 9.2.0+的getbbox) bbox = draw.textbbox((0, 0), text, font=font) text_width = bbox[2] - bbox[0] text_height = bbox[3] - bbox[1] 平铺水印 step_x = text_width + 100 step_y = text_height + 100 for y in range(-text_height, height + step_y, step_y): for x in range(-text_width, width + step_x, step_x): 旋转单个水印 rotated_text = Image.new('RGBA', (text_width + 20, text_height + 20), (255, 255, 255, 0)) rotated_draw = ImageDraw.Draw(rotated_text) rotated_draw.text((10, 10), text, font=font, fill=(WATERMARK_COLOR, int(255 WATERMARK_OPACITY))) rotated_text = rotated_text.rotate(WATERMARK_ANGLE, expand=1) 计算旋转后的左上角坐标 rw, rh = rotated_text.size watermark_layer.paste(rotated_text, (x - rw//2, y - rh//2), rotated_text) 合并原图和水印 result = Image.alpha_composite(img, watermark_layer).convert('RGB') output = BytesIO() result.save(output, format=img.format if img.format else 'JPEG') output.seek(0) return output 下载档案接口 @app.route('/download/启动系统
回到watermark-archive项目根目录,打开终端(Windows用PowerShell/CMD,macOS/Linux用Terminal),执行以下命令:
等待1-2分钟,直到两个容器都启动完成,可通过docker-compose ps查看状态,当STATUS列显示Up时表示成功。
上传档案并测试带水印下载
1. 登录MinIO Web Console
在浏览器中访问http://你的服务器IP:9001(本地测试用http://localhost:9001),输入在docker-compose.yml中设置的MINIO_ROOT_USER和MINIO_ROOT_PASSWORD登录。
2. 上传测试档案
登录后点击左侧菜单的Buckets,找到自动创建的archives存储桶,点击进入后点击右上角Upload按钮,选择一张图片(如test.jpg)上传。
3. 测试带水印下载
在浏览器地址栏输入:http://你的服务器IP:5000/download/test.jpg?username=张三(本地用http://localhost:5000/download/test.jpg?username=张三),按下回车即可下载带有“内部资料 请勿外传\n用户: 张三\n时间: [你的IP]”水印的图片。
后续优化说明
- 修改水印样式:可通过修改
config.py中的参数或在docker-compose.yml的watermark-service服务下添加environment字段覆盖环境变量(修改后需执行docker-compose restart watermark-service生效)。 - 扩展PDF水印:可使用
PyPDF2或pdfplumber库添加PDF水印,只需在app.py的download_file函数中新增PDF判断分支即可。 - 权限控制:可接入简单的Token验证或MinIO的IAM权限,防止未授权下载。