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

graphene-django如何接收文件输入?UploadMutation上传失败排查

graphene-django GraphQL文件上传失败排查与实现方案

问题原因

  • 缺少文件上传依赖与中间件配置:graphene-django默认仅解析application/json类型请求,无法识别multipart/form-data格式的文件上传请求,未配置对应解析逻辑时,文件参数不会被传递到Mutation的mutate方法中。
  • 代码逻辑错误:mutate方法接收到的file参数是Django封装的UploadedFile文件对象,不是字符串路径,直接调用.endswith()会抛出属性错误,无法正常返回结果;代码中存在拼写错误formate,正确拼写为format。
  • 调用方式错误:GraphQL文件上传不支持直接将文件内容写在查询语句文本中,必须遵循multipart请求规范拆分参数提交,直接在mutation语句中写file: xxx无法传递真实文件内容。
  • 未正确注册Schema:如果关闭了graphene的自动驼峰转换,查询语句中的uploadFile与定义的upload_file字段不匹配,会直接报字段不存在错误;若未将FileUploadMutation注册到根Mutation类型,接口也无法识别该字段。

正确实现步骤

1. 安装依赖

pip install graphene-file-upload

2. 修改Django配置

首先在settings.py中添加应用:

INSTALLED_APPS = [
    # 原有其他应用
    "graphene_django",
    "graphene_file_upload",
]

然后修改urls.py中的GraphQL路由,替换默认视图为支持文件上传的视图:

from django.urls import path
from graphene_file_upload.django import FileUploadGraphQLView
# 替换为你自己项目的schema导入路径
from .schema import schema

urlpatterns = [
    # 原有其他路由
    path("graphql", FileUploadGraphQLView.as_view(graphiql=True, schema=schema)),
]

3. 修正Mutation代码

import graphene
from graphene_file_upload.scalars import Upload
from graphql import GraphQLError

class UploadMutation(graphene.Mutation):
    class Arguments:
        file = Upload(required=True)

    success = graphene.Boolean()

    def mutate(self, info, file, **kwargs):
        # 取文件对象的name属性判断后缀
        if not file.name.lower().endswith(".xlsx"):
            raise GraphQLError('File format should be "xlsx".')
        
        # 此处可添加自定义文件保存逻辑,示例:
        # import os
        # save_path = os.path.join("your_upload_dir", file.name)
        # with open(save_path, "wb+") as f:
        #     for chunk in file.chunks():
        #         f.write(chunk)

        return UploadMutation(success=True)


class FileUploadMutation(graphene.ObjectType):
    upload_file = UploadMutation.Field()

# 必须将Mutation注册到Schema根类型,示例:
# class Query(graphene.ObjectType):
#     test = graphene.String()
# 
# class Mutation(FileUploadMutation, graphene.ObjectType):
#     pass
# 
# schema = graphene.Schema(query=Query, mutation=Mutation)

正确调用方式

文件上传必须使用multipart/form-data格式提交请求,请求体包含三个固定部分:

  • operations:JSON格式,存储GraphQL查询语句与变量,文件对应变量位置先填null占位
  • map:JSON格式,映射表单中文件字段到variables内的对应路径
  • 文件字段:键与map中定义的键一致,值为待上传的本地文件

前端Fetch调用示例

// 取input选择的文件
const file = document.querySelector("input[type=file]").files[0];

const operations = JSON.stringify({
  query: `
    mutation UploadFile($file: Upload!) {
      uploadFile(file: $file) {
        success
      }
    }
  `,
  variables: { file: null }
});

const map = JSON.stringify({
  "file_field": ["variables.file"]
});

const formData = new FormData();
formData.append("operations", operations);
formData.append("map", map);
formData.append("file_field", file);

fetch("/graphql", {
  method: "POST",
  body: formData,
  // 不要手动设置Content-Type,让浏览器自动生成带boundary的请求头
})
.then(res => res.json())
.then(res => console.log(res));

Postman调用步骤

  1. 请求方法选择POST,地址填写你的GraphQL接口地址
  2. Body面板选择form-data类型
  3. 添加三个表单项:
    • 键为operations,类型选Text,值为上述operations对应的JSON字符串
    • 键为map,类型选Text,值为上述map对应的JSON字符串
    • 键为file_field,类型选File,值选择本地待上传的xlsx文件
  4. 直接发送请求即可

注意事项

  • 不要手动为multipart请求设置Content-Type请求头,必须让客户端自动生成带boundary分隔符的头,否则服务端无法解析参数
  • 若项目开启了CSRF校验,需要给接口添加CSRF豁免或在请求中携带合法CSRF token,否则会被Django拦截
  • 上传大文件时,提前调整settings.py中FILE_UPLOAD_MAX_MEMORY_SIZE、DATA_UPLOAD_MAX_MEMORY_SIZE参数,避免请求被拦截

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:27:26