Flutter上传File类型文件至PHP数据库报Uint8List转String错误解决方法
错误原因
type 'Uint8List' is not a subtype of type 'String' in type cast 报错的核心原因:
- 普通POST请求默认使用application/x-www-form-urlencoded编码,该格式仅支持字符串类型的键值对,直接将二进制
Uint8List类型的文件字节传入body时,请求框架会强制将所有value转换为String,类型不匹配直接触发报错。 - 二进制文件上传不能使用普通表单格式,必须使用multipart/form-data编码格式的请求传输。
代码修改方案
Flutter端调整
原有文件选择、文件转字节的逻辑无需修改,仅需替换POST请求构造逻辑,使用Multipart格式封装文件数据:
import 'package:http/http.dart' as http; final url = Uri.parse("http://10.0.2.2:8000/api/addSurvey"); // 初始化multipart类型POST请求 final request = http.MultipartRequest('POST', url); // 添加鉴权请求头 request.headers.addAll({ 'Authorization': token, }); // 若有其他普通字符串类型的表单参数,直接添加到fields即可 // request.fields['survey_id'] = "123"; // 封装文件字段 request.files.add( http.MultipartFile.fromBytes( 'bill_image', // 字段名必须和后端接收参数名保持一致 imgbytes, // 之前读取到的Uint8List文件字节 filename: 'upload_${DateTime.now().millisecondsSinceEpoch}.${myfile.path.split('.').last}', // 携带带后缀的文件名 ) ); // 发送请求 final streamedResp = await request.send(); // 转换为常规响应对象处理返回结果 final response = await http.Response.fromStream(streamedResp); // 后续通过response.statusCode、response.body处理业务逻辑即可
如果项目使用dio库发送请求,对应文件上传代码如下:
import 'package:dio/dio.dart'; final dio = Dio(); final formData = FormData.fromMap({ // 其他普通参数正常传即可 'bill_image': MultipartFile.fromBytes( imgbytes, filename: 'upload_${DateTime.now().millisecondsSinceEpoch}.${myfile.path.split('.').last}', ), }); final response = await dio.post( "http://10.0.2.2:8000/api/addSurvey", data: formData, options: Options( headers: {'Authorization': token}, ), );
PHP后端接收注意事项
multipart/form-data格式的文件无法通过php://input直接读取,必须通过$_FILES全局变量获取,参考实现:
<?php // 跨域配置按需调整 header('Access-Control-Allow-Origin: *'); header('Access-Control-Allow-Headers: Authorization, Content-Type'); header('Content-Type: application/json; charset=utf-8'); // 校验文件是否上传成功 if (!isset($_FILES['bill_image']) || $_FILES['bill_image']['error'] !== UPLOAD_ERR_OK) { echo json_encode(['code' => 400, 'msg' => '文件接收失败']); exit; } $uploadFile = $_FILES['bill_image']; // 定义存储路径,注意提前创建uploads目录并授予写入权限 $savePath = './uploads/'.time().'_'.basename($uploadFile['name']); if (move_uploaded_file($uploadFile['tmp_name'], $savePath)) { // 此处可将文件存储路径写入数据库 echo json_encode(['code' => 200, 'msg' => '上传成功', 'file_path' => $savePath]); } else { echo json_encode(['code' => 500, 'msg' => '文件保存失败,请检查目录权限']); } ?>
常见避坑点
- 安卓模拟器访问本地电脑部署的PHP服务使用
10.0.2.2地址时,需确保PHP服务监听地址为0.0.0.0:8000,不要绑定仅localhost可访问。 - 上传文件体积较大时,需修改php.ini配置中
upload_max_filesize、post_max_size参数,调整允许上传的文件大小上限。 - 多文件上传时,只需在files/FormData中追加多个文件字段即可。
内容的提问来源于stack exchange,提问作者Suraj Bhandari Nephop
相关产品推荐
相关产品推荐

