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

Flutter Web图片上传后JSON响应缺失图片类型问题

Flutter Web图片上传后JSON响应缺失图片扩展名问题

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

JSON Response对比

当前代码

图片选择部分

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来识别文件类型,并返回带正确扩展名的文件名。当前代码存在两个关键问题:

  1. 上传时指定的filename是固定的"image",没有保留原文件的扩展名;
  2. 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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 16:33:09