Dart/Flutter如何读取谷歌云端硬盘公开文件内容?
Hey there! Let's fix this problem step by step. First off, the file.readAsLines() method you're using is for reading local files on your Android device, not files stored in Google Drive—so that's why it's totally ineffective here. Let's break down the proper way to authenticate and fetch your public Drive file content:
Your current code tries to create a local File object using what I assume is either a Drive file ID or URL. Since that file doesn't exist on your app's local storage, the read operation will always fail. We need to use the Google Drive API to pull the file content over the network instead.
Since your file is set to "Anyone with the link can view", you have two simple options—no need for full OAuth user login unless you specifically require it:
Option A: Use an API Key (Recommended for Public Files)
This is the simplest approach because public files don't require user authentication. Here's how to do it:
- First, make sure you've enabled the Google Drive API in your Google Cloud Console
- Grab your API key from the Console (under Credentials)
- Use the Drive API's
files.getendpoint with thealt=mediaparameter to download the file content directly
Here's a working example using OkHttp (you'll need to add OkHttp to your app's dependencies):
// Replace these with your actual values val apiKey = "YOUR_GOOGLE_CLOUD_API_KEY" val driveFileId = "YOUR_PUBLIC_FILE_ID" val apiUrl = "https://www.googleapis.com/drive/v3/files/$driveFileId?alt=media&key=$apiKey" val okHttpClient = OkHttpClient() val request = Request.Builder().url(apiUrl).build() okHttpClient.newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { // Handle request failures (e.g., network issues) e.printStackTrace() } override fun onResponse(call: Call, response: Response) { if (response.isSuccessful) { // Get the full file content as a string val fileContent = response.body?.string() // Split into lines, just like you tried with readAsLines() val dogLinks = fileContent?.split("\n") ?: emptyList() // Now use your dogLinks list as needed! // Remember to run UI updates on the main thread if needed } else { // Handle errors (e.g., invalid file ID, API key issues) Log.e("DriveFetch", "Failed to fetch file: ${response.code}") } } })
Option B: Use Your Existing OAuth Token
If you already have a valid OAuth access token (with the drive.readonly scope), you can skip the API key and instead authenticate via an Authorization header:
val driveFileId = "YOUR_PUBLIC_FILE_ID" val oauthToken = "YOUR_VALID_OAUTH_TOKEN" val apiUrl = "https://www.googleapis.com/drive/v3/files/$driveFileId?alt=media" val okHttpClient = OkHttpClient() val request = Request.Builder() .url(apiUrl) .addHeader("Authorization", "Bearer $oauthToken") .build() // The rest of the callback logic is identical to the API key example above
- API Key Restrictions: Make sure you restrict your API key to your Android app's package name and SHA-1 fingerprint in the Google Cloud Console—this prevents unauthorized use of your key.
- Large Files: If your text file is very large, avoid reading the entire content into memory at once. Use a streaming approach instead (OkHttp supports this with
response.body?.byteStream()). - Public File Permissions: Double-check that your Drive file is truly set to "Anyone with the link can view"—if it's restricted to specific users, even an API key won't work.
Quick reminder about your original code:
final file = new File(dogListTxt); Future<List<String>> dogLinks = file.readAsLines();This code looks for a file on your app's local storage using
dogListTxtas a path. Since that path doesn't point to a local file (it's a Drive ID/URL), the read operation will always fail. Always use network requests for cloud-hosted files!
内容的提问来源于stack exchange,提问作者Zoltán Györkei

