Flutter报错:向服务器发送图片时出现“Expected a value of type 'String', but got one of type 'XFile'”错误
解决XFile格式图片上传REST API的错误问题
你遇到的错误确实和XFile格式直接放入请求体有关——当你用普通的http.post并传入包含XFile的Map时,Dart会尝试把这个Map序列化成JSON,但XFile是一个无法被JSON序列化的对象,所以抛出了类型不匹配的错误。而且文件上传需要使用multipart/form-data格式,而不是默认的application/json。
下面是具体的修复步骤和代码调整:
1. 重构文件上传的请求方式
我们需要改用http.MultipartRequest来构建包含文件的请求,而不是直接传递JSON。调整你的Repository层代码:
Future<ApiResponse> sendBankSlip(BankSlipRequest bankSlipRequest) async { ApiResponse apiResponse; try { // 初始化multipart POST请求 var multipartRequest = http.MultipartRequest( 'POST', Uri.parse(_url + "/courses/create-payment"), ); // 添加文本类型的请求参数 multipartRequest.fields['course_Id'] = bankSlipRequest.courseId; multipartRequest.fields['paid_amount'] = bankSlipRequest.paidAmount; // 添加图片文件(如果存在) if (bankSlipRequest.slip != null) { final slipFile = await http.MultipartFile.fromPath( 'proof_image', // 要和服务器端接收的参数名一致 bankSlipRequest.slip!.path, filename: bankSlipRequest.slip!.name, // 可选:传递文件名给服务器 ); multipartRequest.files.add(slipFile); } // 添加请求头(保持你原有的_header配置) multipartRequest.headers.addAll(_headers); // 发送请求并获取响应 final streamedResponse = await multipartRequest.send(); final response = await http.Response.fromStream(streamedResponse); apiResponse = _returnResponse(response); } on SocketException { logger.e('No net'); throw FetchDataException('No Internet connection'); } return apiResponse; }
2. 调整BankSlipRequest类的toJson方法
既然我们不再用JSON格式传递文件,你可以把slip从toJson中移除,避免不必要的序列化问题:
Map<String, dynamic> toJson() => { "course_Id": courseId, "paid_amount": paidAmount, };
3. 确认服务器端配置
确保你的服务器端接口/courses/create-payment支持接收multipart/form-data格式的请求,并且参数名proof_image、course_Id、paid_amount和你代码中使用的完全一致。
为什么原来的代码会报错?
- 你原有的
http.post方法使用body: body时,默认会把Map序列化为JSON,但XFile是一个包含文件路径、名称等属性的对象,无法被JSON序列化,所以抛出了Expected a value of type 'String', but got one of type 'XFile'的错误。 - 文件上传必须使用
multipart/form-data格式,这种格式允许同时传递文本字段和二进制文件数据,是HTTP协议中上传文件的标准方式。
内容的提问来源于stack exchange,提问作者Kavishka Rajapakshe
相关产品推荐
相关产品推荐

