Flutter Dio发送FormData遇415错误,求正确传文件及进度显示方案
解决Dio上传FormData出现415错误及实现上传进度、响应获取的方案
错误原因分析
415错误是因为请求的Content-Type设置错误:你手动指定了application/json,但发送的是FormData,API无法识别这种格式。另外,文件列表的处理存在异步问题,map里的async会返回Future<MultipartFile>的列表,而非直接的MultipartFile列表,导致FormData构造异常。
修正后的完整代码
1. 初始化Dio(移除错误的Content-Type)
Dio dio = Dio( BaseOptions( baseUrl: baseUrl, headers: { 'Accept': 'application/json', 'Authorization': 'Bearer ${APIVariables.token}', // 移除Content-Type: application/json,Dio会自动为FormData设置multipart/form-data }, ), );
2. 正确构造FormData(处理文件异步列表)
// 先处理文件列表,等待所有MultipartFile创建完成 List<MultipartFile> files = await Future.wait( complaint.files.map((file) async => MultipartFile.fromFile( file.path, filename: basename(file.path), )), ); FormData formData = FormData.fromMap({ "id": complaint.id, "title": complaint.title, "description": complaint.description, "complainedPosition": complaint.complainedPosition, "deptId": complaint.departmentId, "typeId": complaint.typeId, "priortyId": complaint.priorityId, "files": files, });
3. 发送请求并监听上传进度、获取响应
try { Response response = await dio.post( 'Complaint', data: formData, // 监听上传进度 onSendProgress: (int sent, int total) { if (total != -1) { double progress = (sent / total) * 100; print('上传进度:${progress.toStringAsFixed(2)}%'); // 这里可以更新UI显示进度,比如用StatefulWidget的setState } }, ); // 上传完成后处理响应 if (response.statusCode == 200 || response.statusCode == 201) { print('上传成功,响应数据:${response.data}'); // 根据API返回的结构处理业务逻辑 } } on DioException catch (e) { // 捕获错误并处理 print('上传失败:${e.message}'); if (e.response != null) { print('响应错误信息:${e.response?.data}'); } }
关键注意点
- Content-Type自动处理:当发送FormData时,Dio会自动添加
Content-Type: multipart/form-data; boundary=xxx的请求头,无需手动设置,手动设置反而会导致格式不匹配。 - 异步文件列表处理:
MultipartFile.fromFile是异步方法,必须用Future.wait等待所有文件实例创建完成后再传入FormData,否则会传入Future对象而非实际的文件对象。 - 进度监听:通过
onSendProgress回调可以获取已发送字节数和总字节数,计算出进度百分比后更新UI。 - 错误捕获:使用
try-catch捕获DioException,可以区分网络错误、响应错误等不同情况,方便调试和用户提示。
内容的提问来源于stack exchange,提问作者Mohammad Alamoudi
相关产品推荐
相关产品推荐

