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

Flutter上传视频到REST API报错type '_File'非String子类型求助

报错原因

  • 直接触发异常的原因:http.post默认将Map类型的body识别为x-www-form-urlencoded格式,要求所有键值对的value都必须是String类型,你代码中存在把_File类型对象直接传入body value的情况,触发了类型转换异常。
  • 代码中还存在3个隐藏问题:
    1. createVideo函数明明定义了file传入参数,但函数内部没有使用该参数,反而直接读取全局的_video变量,逻辑混乱容易出现空值/错值问题
    2. 拍摄视频后初始化播放器的顺序错误:在_video还没完成赋值的情况下就调用VideoPlayerController.file(_video!),大概率会触发空安全异常
    3. 用readAsBytesSync同步读取视频文件+base64编码上传的方式性能极差,大体积视频很容易导致界面卡顿无响应,也会额外增加30%左右的带宽消耗

修复方案

推荐方案:改用multipart/form-data格式上传文件(性能更好,适配绝大多数后端接口规范)

// 需导包:import 'package:http_parser/http_parser.dart';
Future createVideo(String user_id, File file) async {
  // 构造multipart请求
  var request = http.MultipartRequest('POST', Uri.parse('替换为你的实际API地址'));
  // 添加普通文本参数
  request.fields['user_id'] = user_id;
  // 添加视频文件参数
  request.files.add(await http.MultipartFile.fromPath(
    'file', 
    file.path,
    contentType: MediaType('video', 'mp4'),
  ));
  // 发送请求并读取返回结果
  var response = await request.send();
  var responseBody = await response.stream.bytesToString();
  final responseJson = json.decode(responseBody);
  print(responseJson);
}

修正拍摄上传的业务逻辑

Future _pickVideoFromCamera() async {
  final pickVideo = await picker.pickVideo(source: ImageSource.camera);
  // 用户取消拍摄直接返回
  if (pickVideo == null) return;
  // 先给_video赋值,再初始化播放器
  setState(() {
    _video = File(pickVideo.path);
  });
  videoPlayerController = VideoPlayerController.file(_video!)
    ..initialize().then((_) {
      setState(() {});
      videoPlayerController!.play();
    });
  SharedPreferences prefs = await SharedPreferences.getInstance();
  var myId = prefs.getString('user_id');
  if (myId == null || _video == null) return;
  // 调用上传接口
  createVideo(myId, _video!);
}

如果你确定要继续使用base64方式上传的修复版本

Future createVideo(String user_id , File file) async {
  String base64File = '';
  if (await file.exists()) {
    // 改用异步方式读文件,避免阻塞主线程
    final fileBytes = await file.readAsBytes();
    base64File = 'data:video/mp4;base64,' + base64Encode(fileBytes);
  }
  final response = await http.post(
    Uri.parse('替换为你的实际API地址'),
    body: {
      'user_id': user_id,
      'file': base64File,
    },
  );
  // 原代码多余的json.encode可以直接去掉,response.body本身就是字符串
  final responseJson = json.decode(response.body);
  print(responseJson);
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.30 02:45:04