Skip to content

文件上传 ​

说明

项目提供本地文件上传功能,支持图片和通用文件上传,内置扩展名白名单、大小限制、魔术字节校验和路径遍历防护。服务层位于 src/modules/upload/service.py,路由位于 src/modules/upload/router.py。

功能概述 ​

文件上传模块提供统一的文件上传接口 upload_file,支持图片、文档、压缩包等各类文件,通过 UPLOAD_ALLOWED_EXTS 配置控制允许上传的格式。

POST /api/v1/upload/uploadFile  —— 统一文件上传入口

配置项 ​

在 .env 中配置上传相关参数:

bash
# 允许上传的文件扩展名(逗号分隔,留空使用内置智能集合)
UPLOAD_ALLOWED_EXTS=.jpg,.png,.gif,.bmp,.pdf,.doc,.docx,.xls,.xlsx,.ppt,.pptx,.zip,.rar

# 单文件大小上限(MB)
UPLOAD_MAX_SIZE_MB=10

# 上传文件存储根目录
FLASK_UPLOAD_DIR=E:\upload

# 文件访问域名(Nginx 或本地代理)
FLASK_FILE_URL=http://127.0.0.1:8021/api/file

温馨提示

UPLOAD_ALLOWED_EXTS 配置的扩展名会与内置安全集合取交集,确保不会绕过安全校验。留空时回落到内置智能集合。

安全机制 ​

上传模块内置多层安全防护:

1. 路径遍历防护 ​

python
def _is_safe_filename(filename: str) -> bool:
    """拒绝包含路径分隔符或 .. 的文件名"""
    normalized = os.path.normpath(filename)
    if '..' in normalized.split(os.sep):
        return False
    basename = os.path.basename(normalized)
    return basename == normalized or basename == filename

2. 高危格式黑名单 ​

.exe、.bat、.sh、.ps1、.js、.vbs、.svg、.webp 等高危格式无论配置如何一律拒绝。

3. 魔术字节校验 ​

通过 verify_file_magic() 校验文件头部魔术字节,防止伪造扩展名绕过白名单。

4. 流式大小校验 ​

python
def _read_upload_limited(file, max_size_bytes):
    """流式读取,超过大小上限立即中断,避免整文件读入内存"""
    chunks = []
    total = 0
    while True:
        chunk = file.read(65536)
        if not chunk:
            break
        total += len(chunk)
        if total > max_size_bytes:
            return None, R.failed(msg=f"文件大小超过限制,最大允许 {UPLOAD_MAX_SIZE_MB}MB")
        chunks.append(chunk)
    return b''.join(chunks), None

文件命名规则 ​

上传文件自动重命名,格式为:年月日时分秒 + 5位随机数 + 扩展名

python
def _generate_filename(ext_with_dot):
    timestamp = time.strftime('%Y%m%d%H%M%S')
    random_num = '%05d' % random.randint(0, 99999)
    return f"{timestamp}{random_num}{ext_with_dot}"

文件按日期分目录存储:{UPLOAD_DIR}/{YYYYMMDD}/{文件名}

接口调用 ​

上传文件 ​

POST /api/v1/upload/uploadFile
Content-Type: multipart/form-data
Authorization: Bearer <token>
参数: file(文件字段)

响应示例:

json
{
    "code": 0,
    "msg": "上传成功",
    "data": {
        "originalName": "photo.jpg",
        "fileExtension": "jpg",
        "fileType": "image/jpeg",
        "fileSize": 306995,
        "fileName": "2025030614302512345.jpg",
        "filePath": "/20250306/2025030614302512345.jpg",
        "fileUrl": "http://127.0.0.1:8021/api/file/20250306/2025030614302512345.jpg"
    },
    "ok": true
}

前端集成 ​

前端使用 Upload 组件上传,上传成功后将返回的 fileUrl 存入业务字段。详见 文件上传联调 章节。

总结 ​

文件上传模块通过扩展名白名单、魔术字节校验、流式大小限制、路径遍历防护等多层安全机制,确保上传功能的安全性。文件自动重命名并按日期分目录存储,避免文件名冲突和信息泄露。统一的 uploadFile 接口同时支持图片和各类文件上传。

小蚂蚁云团队 · 提供技术支持