Flutter Web图片上传后JSON响应缺失图片类型问题
Flutter Web图片上传后JSON响应缺失图片扩展名问题
近期在Flutter Web项目中实现图片上传到服务器,上传流程能正常完成,服务器端图片显示正常,且确认后端上传逻辑无问题,但返回的JSON响应里图片字段始终没有扩展名。对比Postman上传的正确结果(黄色区域),Flutter Web上传的结果(绿色区域)存在明显异常。

当前代码
图片选择部分
List<int>? _selectedFile; Uint8List? _bytesData; startWebFilePicker() async { FileUploadInputElement uploadInput = FileUploadInputElement(); uploadInput.multiple = true; uploadInput.draggable = false; uploadInput.click(); uploadInput.onChange.listen((event) { final files = uploadInput.files; final file = files![0]; final reader = FileReader(); reader.onLoadEnd.listen((event) { setState(() { _bytesData = Base64Decoder().convert(reader.result.toString().split(",").last); _selectedFile = _bytesData; print('_bytesData -> ${_bytesData}'); }); }); reader.readAsDataUrl(file); }); }
服务器上传部分
Future uploadImage() async { String token = await apiController.getToken(); var url = Uri.parse(conf.url); var request = http.MultipartRequest("POST", url); request.headers['Authorization'] = 'Bearer $token'; request.headers['Content-Type'] = 'multipart/form-data'; request.fields['name'] = 'parent cat'; request.fields['description'] = 'description cat'; request.fields['parent_id'] = ''; request.fields['is_active'] = '1'; request.files.add(await http.MultipartFile.fromBytes( 'image', _selectedFile!, contentType: new MediaType('*', '*'), filename: "image")); request.send().then((response) { if (response.statusCode == 200) { print('response.statusCode -> ${response.stream}'); print("File uploaded successfully"); } else { print('file upload failed'); } }); }
上传后日志输出:File uploaded successfully
问题原因
后端生成JSON响应时,大概率依赖上传文件的文件名(含扩展名)或Content-Type来识别文件类型,并返回带正确扩展名的文件名。当前代码存在两个关键问题:
- 上传时指定的
filename是固定的"image",没有保留原文件的扩展名; contentType设置为通配符*/*,无法提供准确的文件类型标识。
修复方案
1. 图片选择时保留原文件信息
在文件选择逻辑中,新增变量保存原文件的名称和MIME类型:
List<int>? _selectedFile; Uint8List? _bytesData; String? _originalFileName; // 保存原文件名(含扩展名) String? _originalFileType; // 保存原文件MIME类型 startWebFilePicker() async { FileUploadInputElement uploadInput = FileUploadInputElement(); uploadInput.multiple = true; uploadInput.draggable = false; uploadInput.click(); uploadInput.onChange.listen((event) { final files = uploadInput.files; final file = files![0]; final reader = FileReader(); // 保存原文件的名称和类型 _originalFileName = file.name; _originalFileType = file.type; reader.onLoadEnd.listen((event) { setState(() { _bytesData = Base64Decoder().convert(reader.result.toString().split(",").last); _selectedFile = _bytesData; print('_bytesData -> ${_bytesData}'); }); }); reader.readAsDataUrl(file); }); }
2. 上传时使用正确的文件信息
修改上传逻辑,使用原文件名和准确的Content-Type,同时移除手动设置的Content-Type(MultipartRequest会自动处理该头):
Future uploadImage() async { String token = await apiController.getToken(); var url = Uri.parse(conf.url); var request = http.MultipartRequest("POST", url); request.headers['Authorization'] = 'Bearer $token'; // 移除手动设置的Content-Type,避免冲突 // request.headers['Content-Type'] = 'multipart/form-data'; request.fields['name'] = 'parent cat'; request.fields['description'] = 'description cat'; request.fields['parent_id'] = ''; request.fields['is_active'] = '1'; request.files.add(await http.MultipartFile.fromBytes( 'image', _selectedFile!, // 使用原文件的MIME类型, fallback到image/jpeg以防为空 contentType: MediaType.parse(_originalFileType ?? 'image/jpeg'), filename: _originalFileName!)); request.send().then((response) { if (response.statusCode == 200) { print('response.statusCode -> ${response.stream}'); print("File uploaded successfully"); } else { print('file upload failed'); } }); }
这样修改后,后端能获取到带扩展名的文件名和准确的文件类型,返回的JSON响应就会包含正确的图片扩展名了。
内容的提问来源于stack exchange,提问作者Amin Azizzadeh
相关产品推荐
相关产品推荐

