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

Django中如何解析request.body中的Multipart文件并正常保存

解决Java WebClient上传Multipart文件到Django时request.POST/FILES为空的问题

问题原因

  1. Django的APIView默认不会自动解析multipart/form-data类型请求,导致文件数据滞留在request.body中,无法映射到request.POST和request.FILES。
  2. 直接保存request.body会包含multipart请求的边界分隔符、Content-Disposition等头部元数据,并非纯文件内容,因此文件会损坏。

解决方案

步骤1:配置Django APIView的请求解析器

给UpdateJiraAppLogo类添加解析器配置,让Django自动解析multipart请求,将文件存入request.FILES:

from rest_framework.parsers import MultiPartParser, FormParser
from rest_framework.views import APIView
from rest_framework import status
from rest_framework.response import Response
from django.utils import timezone

class UpdateJiraAppLogo(APIView):
    # 指定解析multipart请求的解析器
    parser_classes = (MultiPartParser, FormParser)

    def post(self, request, *args, **kwargs):
        print('POST', request.POST)
        print('FILES', request.FILES)
        
        # 从FILES中获取上传的文件
        if 'file' in request.FILES:
            uploaded_file = request.FILES['file']
            now = timezone.now()
            logo_name = f"logo_{now.strftime('%d_%m_%Y_%H%M%S')}.png"
            
            try:
                with open(f"media/logos/{logo_name}", "wb+") as f:
                    # 分块写入,避免大文件占用过多内存
                    for chunk in uploaded_file.chunks():
                        f.write(chunk)
                # with语句会自动关闭文件,无需手动调用close()
            except Exception as e:
                print(e)
                return Response({"error": str(e)}, status=status.HTTP_500_INTERNAL_SERVER_ERROR)
        
        return Response({"status": "success"})

步骤2:优化Java端上传代码(可选,提升兼容性)

显式指定文件名和媒体类型,避免Django解析时出现异常:

public void updateLogo(String clientKey, MultipartFile file) {
    MultipartBodyBuilder builder = new MultipartBodyBuilder();
    // 明确指定文件名和文件类型
    builder.part("file", file.getResource())
           .filename(file.getOriginalFilename())
           .contentType(MediaType.IMAGE_PNG); // 根据实际文件类型调整

    Settings prevData = repo.findFirstByClientKey(clientKey);
    WebClient webClient = WebClient.builder().baseUrl("http://localhost/")
            .defaultHeader(HttpHeaders.AUTHORIZATION, String.format("Token %s", userToken)).build();
    
    Mono<SettingsLogo> resObj = webClient.post().uri("api/upload-logo")
            .contentType(MediaType.MULTIPART_FORM_DATA)
            .body(BodyInserters.fromMultipartData(builder.build()))
            .retrieve().bodyToMono(SettingsLogo.class)
            .onErrorResume(WebClientResponseException.class, ex -> {
                logger.error("Exception", ex);
                return Mono.empty();
            });
}

关键说明

  • MultiPartParser负责解析multipart/form-data请求,提取文件数据到request.FILES;FormParser处理表单字段到request.POST。
  • 使用uploaded_file.chunks()分块写入文件,更适合大文件场景,避免内存溢出。
  • 绝对不能直接操作request.body保存文件,因为其中包含multipart请求的元数据,并非纯净的文件内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 06:56:54