Flask App Builder带文件字段的ModelRestApi POST上传如何正确调用?
Flask-AppBuilder 带文件上传的POST接口正确调用方案
原有调用方式失败的核心问题
- 参数结构不规范:将普通文本字段
description和文件字段一同放入requests.post的files参数中,不符合FAB REST接口对multipart/form-data请求的解析规则 - 接口配置缺失:未在ModelRestApi中显式声明允许通过POST接口写入的字段,FAB默认会拦截FileColumn这类特殊字段的写入请求
- 鉴权逻辑不匹配:仅开启
allow_browser_login仅支持浏览器端会话鉴权,非浏览器调用需要携带有效的认证Header
服务端接口配置调整(基于现有代码)
在原有FileApi类的基础上补充字段声明配置,不需要额外编写自定义上传逻辑:
class FileApi(ModelRestApi): resource_name = "File" datamodel = SQLAInterface(Files) allow_browser_login = True # 显式声明允许通过POST接口新增的字段,必须包含FileColumn对应的file字段 add_columns = ["file", "description"] # 可选:配置文件上传的校验规则 validators_columns = { "file": [ FileSizeValidator(limit_value=10*1024*1024), # 单文件最大10MB FileAllowedExtensions(allowed_extensions=["txt", "pdf", "png"]) ] } appbuilder.add_api(FileApi)
客户端正确调用示例
修正之前的请求参数结构,按规范传递文件和普通字段:
import requests # FAB REST接口默认统一前缀为/api/v1,结合你定义的resource_name,完整接口路径为 url = "http://服务地址/api/v1/File" # 携带有效认证信息,例如通过登录接口获取的JWT Token headers = { "Authorization": "Bearer 你的有效JWT令牌" } # 文件参数:需明确指定文件名、文件流、文件类型 files = { "file": ("test.txt", open("test.txt", "rb"), "text/plain") } # 普通表单字段:独立放入data参数,不要混入files字典 data = { "description": "test" } response = requests.post(url, headers=headers, files=files, data=data) print(response.json())
灵活自定义上传的替代方案
如果需要脱离ModelRestApi的自动解析逻辑、自定义存储流程,可以在常规ModelView中实现独立的上传路由:
from flask import request, jsonify from flask_appbuilder import ModelView, expose class ProjectFilesModelView(ModelView): datamodel = SQLAInterface(Files) @expose("/custom_upload", methods=["POST"]) def custom_upload(self): uploaded_file = request.files.get("file") desc = request.form.get("description", "") if not uploaded_file: return jsonify({"msg": "未检测到上传文件"}), 400 # 自行实现文件存储、数据库写入逻辑 file_record = Files( file=uploaded_file, description=desc ) self.datamodel.add(file_record) return jsonify({"id": file_record.id, "msg": "上传成功"})
常见踩坑提示
- 注意:FAB自动解析文件上传的逻辑仅支持
multipart/form-data格式的请求,不支持纯JSON格式传递文件内容 - 确保应用初始化时配置了可读写的
APP_MEDIA_FOLDER路径,否则FileColumn会因为无存储权限写入失败 - 不要在
files参数中传入非文件类型的键值对,否则会导致请求体编码异常,触发接口解析失败
内容的提问来源于stack exchange,提问作者Hyoungki Kim
相关产品推荐
相关产品推荐

