如何在Flutter中通过带请求体与请求头的POST请求下载PDF文件?
解决Flutter中使用Dio通过POST请求下载PDF并打开的问题
嘿,作为Flutter新手遇到这个问题很正常,我来一步步帮你搞定它!其实Dio的download方法是支持自定义请求方法、请求体和请求头的,只是默认是GET而已,另外文件存储和打开的部分我们可以借助两个常用插件来实现。
步骤1:添加必要的依赖
首先,在你的pubspec.yaml里添加三个依赖:
dio:处理网络请求path_provider:获取设备的标准存储路径open_file:打开本地文件
dependencies: flutter: sdk: flutter dio: ^5.4.0 # 请使用最新版本 path_provider: ^2.1.2 open_file: ^3.3.2
执行flutter pub get完成依赖安装。
步骤2:实现带POST请求体的下载逻辑
我们可以通过Dio的download方法的options参数,指定请求方法为POST,同时传入请求体和请求头。另外用path_provider获取内部存储的downloads目录,确保文件存到正确的位置。
完整代码示例:
import 'dart:io'; import 'package:dio/dio.dart'; import 'package:path_provider/path_provider.dart'; import 'package:open_file/open_file.dart'; Dio dio = Dio(); Future<APIResponse> downloadAndOpenPdf({required String token}) async { try { // 1. 获取设备的Downloads目录路径 Directory? downloadsDir; if (Platform.isAndroid) { // Android 获取公共下载目录 downloadsDir = await getExternalStoragePublicDirectory(DirectoryDownloads); } else if (Platform.isIOS) { // iOS 获取应用内的Documents目录(可按需调整) downloadsDir = await getApplicationDocumentsDirectory(); } if (downloadsDir == null) { throw Exception("无法获取存储目录"); } // 确保目录存在 await downloadsDir.create(recursive: true); // 2. 定义文件保存路径(示例命名为january_2022.pdf) String filePath = "${downloadsDir.path}/january_2022.pdf"; // 3. 使用Dio执行POST下载 Response response = await dio.download( 'https://www.example.com/sample/download', filePath, options: Options( method: 'POST', // 指定请求方法为POST headers: { 'Authorization': 'Bearer $token', }, ), data: {"month": "January", "year": "2022"}, // 传入POST请求体 // 可选:添加下载进度监听 onReceiveProgress: (received, total) { if (total != -1) { print("下载进度:${(received / total * 100).toStringAsFixed(0)}%"); } }, ); if (response.statusCode == 200) { // 4. 下载成功后打开文件 await OpenFile.open(filePath); return APIResponse.fromJson(response.data); // 适配你的APIResponse解析逻辑 } else { throw Exception("下载失败,状态码:${response.statusCode}"); } } catch (e) { // 处理异常:网络错误、存储权限不足等 print("下载出错:$e"); rethrow; // 或根据需求返回错误状态的APIResponse } }
关键细节说明
- Dio下载方法的自定义配置:通过
options.method指定POST请求,data参数直接传入请求体,完全满足你的需求,无需手动处理文件写入逻辑。 - 跨平台存储路径:
path_provider统一了Android和iOS的存储路径获取,避免了手动拼接路径的兼容性问题。注意Android 10+的Scoped Storage机制,如果遇到权限问题,可调整存储路径到应用私有目录,或在AndroidManifest.xml中添加相应权限声明。 - 本地文件打开:
open_file插件会调用系统默认应用打开PDF,无需自己实现文件解析逻辑。
额外注意事项
- 权限配置:Android需在
AndroidManifest.xml中添加READ_EXTERNAL_STORAGE、WRITE_EXTERNAL_STORAGE(Android 13+可调整为READ_MEDIA_IMAGES等);iOS需在Info.plist中添加文件访问相关权限描述。 - 异常处理:可根据业务需求优化异常捕获逻辑,比如给用户展示Toast提示下载失败原因。
内容的提问来源于stack exchange,提问作者kl23
相关产品推荐
相关产品推荐

