Flutter上传视频到REST API报错type '_File'非String子类型求助
报错原因
- 直接触发异常的原因:
http.post默认将Map类型的body识别为x-www-form-urlencoded格式,要求所有键值对的value都必须是String类型,你代码中存在把_File类型对象直接传入body value的情况,触发了类型转换异常。 - 代码中还存在3个隐藏问题:
createVideo函数明明定义了file传入参数,但函数内部没有使用该参数,反而直接读取全局的_video变量,逻辑混乱容易出现空值/错值问题- 拍摄视频后初始化播放器的顺序错误:在
_video还没完成赋值的情况下就调用VideoPlayerController.file(_video!),大概率会触发空安全异常 - 用
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
相关产品推荐
相关产品推荐

