Flutter录音后如何将音频文件上传至后端?
录音文件上传至后端的实现方案
问题背景
使用audio包录音结束后,得到的是类似file:///private/var/mobile/Containers/Data/Application/xxx/tmp/xxx.m4a的带协议前缀的文件路径,直接用该路径创建File对象上传会失败,需要调整代码实现正确的文件上传。
解决步骤
1. 转换file://路径为本地文件路径
audioRecorder返回的路径包含file://前缀,Dart的File类无法直接识别,需要先去掉前缀:
// 处理audioPath,去掉file://前缀 String localPath = audioPath.replaceFirst('file://', '');
2. 修正Content-Type设置
原代码中直接把文件后缀作为Content-Type是错误的,应该使用对应文件的MIME类型,比如m4a的MIME类型是audio/mp4。可以根据后缀映射对应的MIME类型:
// 根据文件后缀获取正确的MIME类型 String extension = audioPath.split('.').last.toLowerCase(); String mimeType; switch(extension) { case 'm4a': mimeType = 'audio/mp4'; break; case 'mp3': mimeType = 'audio/mpeg'; break; // 其他音频格式可以继续补充 default: mimeType = 'audio/mpeg'; }
3. 使用FormData正确上传文件
后端通常期望通过multipart/form-data格式接收文件,需要用Dio的FormData来包装文件:
void convertToText() async { try { final dio = Dio(); dio.options.headers['api-key'] = Constant.apiKey; // 处理文件路径 String localPath = audioPath.replaceFirst('file://', ''); File audioFile = File(localPath); // 确认文件存在 if (!await audioFile.exists()) { print('文件不存在'); return; } // 获取正确的MIME类型 String extension = audioPath.split('.').last.toLowerCase(); String mimeType = extension == 'm4a' ? 'audio/mp4' : 'audio/mpeg'; // 构建FormData FormData formData = FormData.fromMap({ 'audio': await MultipartFile.fromFile( localPath, filename: 'recording.${extension}', contentType: MediaType.parse(mimeType), ), }); // 发起POST请求 final result = await dio.post( Constant.apiLinkVoiceToText, data: formData, ); print(result.data.toString()); } catch (e) { print('上传失败: $e'); } }
4. 确认路径传递正确性
原代码的_stop方法逻辑没问题,只需保证audioPath正确接收来自widget.onStop(path)的路径即可。
关键注意点
- 必须去除
file://前缀才能正确创建File对象 - 要使用正确的MIME类型,否则后端可能无法识别文件格式
- 上传文件时必须用
multipart/form-data格式(通过FormData实现),而不是直接传递File对象
内容的提问来源于stack exchange,提问作者BSCodeLaKhet
相关产品推荐
相关产品推荐

