Flutter中如何从API返回的文件路径提取文件扩展名?
问题描述
我从API获取到带查询参数的文件路径(示例如下),文件格式可能是pdf、jpeg等。需求是:图片文件在Dialog中展示,PDF文件则触发下载到用户设备。我尝试用split字符串方法提取扩展名但失败了,求解决方法。
示例路径:
https://xuriti-prod-kyc.s3.ap-south-1.amazonaws.com/27AAACB2100P1ZX/1675230131954-download-%281%29.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAXALYDECMNE2HOZS7%2F20230216%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20230216T063528Z&X-Amz-Expires=900&X-Amz-Signature=59204e81b56cd325de1531a1e6c6a67c5030c76c0516b4719e40986e1ef1d917&X-Amz-SignedHeaders=hosthttps://xuriti-prod-kyc.s3.ap-south-1.amazonaws.com/27AAACB2100P1ZX/1675230131972-download.jpeg?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=AKIAXALYDECMNE2HOZS7%2F20230216%2Fap-south-1%2Fs3%2Faws4_request&X-Amz-Date=20230216T063528Z&X-Amz-Expires=900&X-Amz-Signature=867311e96282f231406f46d5f2a5d11befe985b0b3a0ab161f69dfb3465b50a9&X-Amz-SignedHeaders=host
我尝试的代码片段:
List imgfiles = []; @override void initState() { init(); super.initState(); } Future init() async { dynamic companyId = getIt<SharedPreferences>().getString('companyId'); dynamic responseData = await getIt<DioClient>().KycDetails(companyId); final details = responseData['data']; Aadhar Docdetails = Aadhar.fromJson(details['aadhar']); setState(() { List<String> imgfiles = Docdetails.files; this.imgfiles = imgfiles; }); } // 列表构建部分 Padding( padding: EdgeInsets.only( left: w1p * 3, right: w1p * 6, ), child: SizedBox( width: maxWidth, height: 50, child: ListView.builder( scrollDirection: Axis.horizontal, itemCount: imgfiles.length, itemBuilder: (context, index) { String doc = imgfiles[index]; print('the whole filepath >>>>>>>>$doc'); String doc1 = doc.split('jpeg').toString(); print('doc1.>>>>>>>>$doc1'); return GestureDetector( onTap: () { showDialog( context: context, builder: (context) { return Dialog( child: Container( width: 220, height: 200, child: Image.network( '$doc', fit: BoxFit.cover, ), ), ); }); }, child: imageDialog()); }, ), ), )
解决方案
直接用split硬编码扩展名的方式不灵活,且URL带有查询参数(?后的部分),需要先解析URL再提取扩展名。可以用Flutter内置的Uri类处理:
1. 编写提取扩展名的工具函数
String getFileExtension(String url) { // 解析URL为Uri对象 Uri uri = Uri.parse(url); // 获取URL的路径部分(去掉查询参数) String path = uri.path; // 拆分路径,取最后一段文件名 String fileName = path.split('/').last; // 拆分文件名,取最后一个.后面的部分作为扩展名 List<String> parts = fileName.split('.'); if (parts.length > 1) { return parts.last.toLowerCase(); // 转小写统一处理,避免大小写问题 } return ''; // 无扩展名时返回空字符串 }
2. 在列表构建中区分文件类型
修改itemBuilder逻辑,根据扩展名判断是图片还是PDF:
itemBuilder: (context, index) { String doc = imgfiles[index]; String extension = getFileExtension(doc); return GestureDetector( onTap: () { if (['jpeg', 'jpg', 'png', 'gif'].contains(extension)) { // 图片文件:弹窗展示 showDialog( context: context, builder: (context) { return Dialog( child: Container( width: 220, height: 200, child: Image.network( doc, fit: BoxFit.cover, ), ), ); }); } else if (extension == 'pdf') { // PDF文件:触发下载逻辑 downloadFile(doc); } }, child: imageDialog()); },
3. 补充PDF下载实现示例(使用dio)
如果还没实现下载逻辑,可参考以下代码:
Future<void> downloadFile(String url) async { try { Response response = await Dio().get( url, options: Options( responseType: ResponseType.bytes, followRedirects: false, ), ); // 从URL路径提取文件名 Uri uri = Uri.parse(url); String fileName = uri.path.split('/').last; // 获取设备存储路径(需permission_handler库申请存储权限) String? downloadPath = await getExternalStorageDirectory()?.path; if (downloadPath != null) { File file = File('$downloadPath/$fileName'); await file.writeAsBytes(response.data); // 提示下载完成 ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('文件已下载到$downloadPath')), ); } } catch (e) { ScaffoldMessenger.of(context).showSnackBar( SnackBar(content: Text('下载失败:$e')), ); } }
注意事项
- 需要添加依赖:
dio(网络请求)、path_provider(获取存储路径)、permission_handler(申请存储权限),在pubspec.yaml中声明。 - 扩展名转小写处理,避免因URL中扩展名大小写不一致导致判断错误。
内容的提问来源于stack exchange,提问作者Minal Suryawanshi
相关产品推荐
相关产品推荐

