Flutter WEB端如何向API上传文件?
Flutter Web API文件上传报错解决方案
实现前提
需要引入两个适配Web的第三方依赖,在pubspec.yaml中添加如下配置:
dependencies: flutter: sdk: flutter dio: ^5.4.1 # 网络请求库,使用最新稳定版即可 file_picker: ^6.1.1 # 文件选择库,已完成全平台适配
完整可运行代码实现
import 'package:flutter/material.dart'; import 'package:file_picker/file_picker.dart'; import 'package:dio/dio.dart'; class FileUploadPage extends StatefulWidget { const FileUploadPage({super.key}); @override State<FileUploadPage> createState() => _FileUploadPageState(); } class _FileUploadPageState extends State<FileUploadPage> { double _uploadProgress = 0; // 选择本地文件 Future<PlatformFile?> _pickLocalFile() async { FilePickerResult? pickResult = await FilePicker.platform.pickFiles( // 可根据需求修改文件类型限制 type: FileType.custom, allowedExtensions: ['pdf', 'png', 'jpg', 'doc'], // Web端必须开启withData,才能直接获取文件二进制流 withData: true, ); if (pickResult != null && pickResult.files.isNotEmpty) { return pickResult.files.first; } return null; } // 上传文件到API Future<void> _uploadToApi(PlatformFile file) async { final Dio dio = Dio(); final FormData formData = FormData.fromMap({ // 补充接口要求的其余表单参数,示例为userId "userId": "10001", // 文件字段名需和后端约定保持一致,示例为uploadFile "uploadFile": MultipartFile.fromBytes( file.bytes!, filename: file.name, ), }); try { await dio.post( // 替换为实际的接口地址 "https://your-api-domain.com/upload", data: formData, options: Options( // 如有鉴权需求,补充对应的请求头 headers: { "Authorization": "Bearer your_token_here", }, ), onSendProgress: (sentBytes, totalBytes) { if (totalBytes != -1) { setState(() { _uploadProgress = sentBytes / totalBytes; }); } }, ); // 上传成功逻辑 if (mounted) { ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text("上传成功"))); } } on DioException catch (e) { // 错误排查输出 debugPrint("错误码: ${e.response?.statusCode}"); debugPrint("接口返回错误信息: ${e.response?.data}"); if (mounted) { ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text("上传失败:${e.response?.statusMessage}"))); } } } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: const Text("文件上传示例")), body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ ElevatedButton( onPressed: () async { PlatformFile? file = await _pickLocalFile(); if (file != null) { await _uploadToApi(file); } }, child: const Text("选择并上传文件"), ), const SizedBox(height: 20), if (_uploadProgress > 0) SizedBox( width: 200, child: LinearProgressIndicator( value: _uploadProgress, backgroundColor: Colors.grey[200], valueColor: const AlwaysStoppedAnimation<Color>(Colors.blue), ), ), ], ), ), ); } }
常见报错排查项
- 平台兼容问题:Flutter Web不支持本地文件路径读取,禁止使用
MultipartFile.fromFile方法,该方法仅适配移动端,Web端必须使用MultipartFile.fromBytes传入文件二进制流 - 跨域错误:如果控制台报CORS相关错误,需要后端配置跨域规则,开放OPTIONS请求权限,允许前端域名、自定义请求头和POST请求方法
- 请求头错误:不要手动设置
Content-Type: multipart/form-data,Dio构造FormData时会自动生成带boundary的合法请求头,手动设置会导致boundary丢失,后端无法解析表单数据 - 参数不匹配:确认文件字段名、其余表单参数、文件名后缀和后端要求完全一致,缺失文件名将导致大部分后端框架识别文件失败
内容的提问来源于stack exchange,提问作者Muhammad Shafique
相关产品推荐
相关产品推荐

