如何在Flutter应用中拉取Google Drive的公开.csv文件
Flutter 拉取Google Drive公开CSV文件实现方案(2024维护版,无废弃API)
前置依赖配置
直接在pubspec.yaml添加以下仍在活跃维护的依赖,不要用老帖子提到的已停更的单独Drive封装包:
dependencies: flutter: sdk: flutter # 官方维护的Google API集合,内置最新版Drive V3接口 googleapis: ^13.2.0 googleapis_auth: ^1.6.0 # CSV解析工具 csv: ^6.0.0 # 基础网络请求库 http: ^1.2.2
执行flutter pub get完成安装。
核心实现步骤
你已经完成登录拿到有效OAuth token、client ID、fileID,直接按以下步骤写逻辑即可:
1. 初始化鉴权客户端
不要用老帖子里废弃的自定义httpClient鉴权写法,直接用官方封装的方法生成带鉴权头的客户端:
import 'dart:convert'; import 'package:googleapis/drive/v3.dart' as drive; import 'package:googleapis_auth/auth_io.dart'; import 'package:http/http.dart' as http; Future<http.Client> initAuthClient(String accessToken, String clientId) async { // 组装你登录拿到的token凭证 final credentials = AccessCredentials( AccessToken( 'Bearer', accessToken, // 替换为你登录接口返回的实际token过期时间 DateTime.now().add(const Duration(hours: 1)).toUtc(), ), null, // 只读公开文件只需要申请只读权限,不要申请全量Drive权限,避免触发安全拦截 ['https://www.googleapis.com/auth/drive.readonly'], ); return authenticatedClient( http.Client(), credentials, clientId: ClientId(clientId, ''), ); }
补充:如果你的CSV是完全公开(共享设置为「知道链接的任何人可查看」),可以跳过鉴权步骤,直接用普通http客户端拉取,不需要走OAuth流程。
2. 拉取CSV文件内容
注意老帖子里常见的错误:直接调用files.get不传下载参数只会返回文件元数据(文件名、修改时间这类信息),拿不到实际内容,必须指定全量下载参数:
Future<String> getCsvContent(String fileId, http.Client client) async { final driveApi = drive.DriveApi(client); // 关键参数:downloadOptions必须设为fullMedia才会返回文件内容 final fileRes = await driveApi.files.get( fileId, downloadOptions: DownloadOptions.fullMedia, ) as drive.Media; // 把返回的字节流转为UTF-8字符串,避免中文乱码 final csvString = await fileRes.stream.transform(utf8.decoder).join(); return csvString; }
如果是无鉴权拉取公开文件,直接替换为普通get请求即可,不需要初始化Drive API实例:
Future<String> getPublicCsvWithoutAuth(String fileId, String apiKey) async { final res = await http.get(Uri.parse( 'https://www.googleapis.com/drive/v3/files/$fileId?alt=media&key=$apiKey' )); if (res.statusCode == 200) { return utf8.decode(res.bodyBytes); } throw Exception('文件拉取失败,状态码:${res.statusCode}'); }
3. 解析CSV并渲染到页面
拿到CSV字符串后直接解析为二维数组,用列表组件展示即可:
import 'package:csv/csv.dart'; import 'package:flutter/material.dart'; Widget showCsvContent(String csvRaw) { // 解析CSV为 行-列 结构的二维数组 final List<List<dynamic>> csvData = const CsvToListConverter().convert(csvRaw); return ListView.separated( padding: const EdgeInsets.all(16), itemCount: csvData.length, separatorBuilder: (_, __) => const Divider(height: 1), itemBuilder: (context, rowIndex) { final row = csvData[rowIndex]; return Padding( padding: const EdgeInsets.symmetric(vertical: 8), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ // 表头行可以单独加样式 if (rowIndex == 0) Text( row.join(' | '), style: const TextStyle(fontWeight: FontWeight.bold, fontSize: 16), ) else Text(row.join(' | ')), ], ), ); }, ); }
常见踩坑说明(对应老帖子里废弃/遗漏的点)
- 旧版本
googleapis包里的大写枚举DownloadOptions.FullMedia已经废弃,现在必须用小写开头的DownloadOptions.fullMedia,否则编译报错 - 新创建的Google Cloud项目默认没有开启Drive API,需要手动到API库搜索Google Drive API启用,否则会报403权限错误
- 不要申请
https://www.googleapis.com/auth/drive全量操作权限,只读文件只需要drive.readonly权限即可,权限过高会触发Google的安全校验,甚至导致应用审核被拒 - 转码必须用
utf8.decoder,不要用默认的系统编码,否则中文、特殊符号会出现乱码 - 如果拉取公开文件提示404,先检查文件共享设置是否真的开启了「任何人可查看」,fileID是否复制完整,不要漏字符
内容的提问来源于stack exchange,提问作者Super_novs
相关产品推荐
相关产品推荐

