Flutter发送Uint8List签名图片至Django ImageField存储失败问题
问题根因
数据库中存储PNG二进制乱码、无法生成可访问图片文件,核心是两处逻辑错误:
- Flutter端构造Multipart上传文件时,未指定带后缀的文件名与图片MIME类型,Django无法识别该请求为文件上传请求
- Django端未配置multipart格式解析器,且错误从
request.data中读取原始二进制内容直接赋值给ImageField,完全跳过Django内置的文件存储、文件名生成、路径拼接逻辑,ImageField无法正常处理原始字节数据
修复方案
1. 调整Flutter端上传代码
补全文件上传必要参数,同时补上缺失的请求发送逻辑,修改后代码如下:
// 顶部需要先导入依赖 import 'package:http_parser/http_parser.dart'; signaturePic(String imgName, SignatureController controller) async{ String completeUrl = '$rootApi/reports/signature_pic/'; var uri = Uri.parse(completeUrl); var request = http.MultipartRequest("POST", uri); Uint8List? signatureFile = await controller.toPngBytes(); if (signatureFile != null){ final multipartFile = http.MultipartFile.fromBytes( imgName, signatureFile, filename: '$imgName.png', // 必须传入带.png后缀的文件名 contentType: MediaType('image', 'png'), // 明确指定文件MIME类型为PNG图片 ); request.files.add(multipartFile); request.headers["authorization"]='TOKEN ${temp.apiKey}'; } // 原代码缺失请求发送逻辑,必须补上 var streamedResponse = await request.send(); var response = await http.Response.fromStream(streamedResponse); debugPrint('上传返回结果:${response.body}'); }
2. 调整Django端视图代码
添加multipart格式解析器,从request.FILES中读取标准上传文件对象再赋值给ImageField,修改后代码如下:
from rest_framework.parsers import MultiPartParser, FormParser from rest_framework import status from rest_framework.response import Response from rest_framework.views import APIView class SignaturePicView(APIView): # 添加multipart解析器,否则DRF无法正确解析上传的文件 parser_classes = [MultiPartParser, FormParser] def post(self, request): try: # 上传的文件统一存放在request.FILES中,字段名与Flutter端传入的MultipartFile字段名一致 for field_name, uploaded_file in request.FILES.items(): items = field_name.split('__') is_return = True if items[5] == 'True' else False SignaturePic.objects.update_or_create( user=request.user, # 直接使用request.user即可,无需重复查询数据库 unique_identifier=field_name, is_return=is_return, defaults={ 'image': uploaded_file, # 传入Django标准UploadedFile对象,ImageField会自动完成存储 } ) return Response(status=status.HTTP_201_CREATED) except Exception as e: print(e) return Response(status=status.HTTP_400_BAD_REQUEST, data={'error': str(e)})
验证标准
代码调整完成后重新发起上传请求,符合以下表现即为修复成功:
- 数据库
SignaturePic表的image字段存储的是类似signatures/xxx.png的相对路径字符串,不再是二进制乱码 - Django配置的
MEDIA_ROOT路径下的signatures目录中,会生成对应的实体PNG文件,可通过配置的MEDIA_URL正常访问
注意:提前确认Django配置文件中
MEDIA_URL、MEDIA_ROOT配置正确,开发环境下需要在urls.py中添加媒体文件的路由映射,否则上传后的图片无法通过HTTP正常访问。
内容的提问来源于stack exchange,提问作者Cesar Rodriguez
相关产品推荐
相关产品推荐

