使用Service Account从Google Drive下载Update.exe文件失败问题
Google Drive服务账号下载大文件内存流为空问题
我尝试用Google Drive结合服务账号实现应用自动更新功能:Google Drive里有个名为Update的文件夹已共享给该服务账号,文件夹内包含记录最新版本号的Version.txt文件和约1MB的Update.exe可执行文件。目前能正常读取Version.txt,但下载Update.exe时,看似执行了下载流程,内存流ms2却始终为空,怀疑和服务账号认证有关,求解决。
相关代码如下:
public class GoogleDriveAccess { //google drive file IDs private readonly static string versionFileID = @"blahblahblahblah"; private readonly static string updateFileID = @"blehblehblehbleh"; //check for updated assembly on google drive and install if authorised public async static void CheckForUpdate() { try { //load json key file from resources into a byte array var jsonFile = Properties.Resources.drive_access; //create service account keyfile from json byte array var serviceAccountKeyfile = System.Text.Encoding.Default.GetString(jsonFile); //create Google credentials with full access from service account keyfile GoogleCredential credential = GoogleCredential.FromJson(serviceAccountKeyfile) .CreateScoped(new[] { DriveService.ScopeConstants.Drive }); //create Google drive service using credentials DriveService service = new DriveService(new BaseClientService.Initializer() { HttpClientInitializer = credential }); //get version file metadata var getRequest = service.Files.Get(versionFileID); //download version file to memory await using var ms = new MemoryStream(); await getRequest.DownloadAsync(ms); //read memory stream into a string ms.Position = 0; var sr = new StreamReader(ms); string textUpdateVersion = sr.ReadToEnd().Trim(); //obtain our current assembly version Version currentVersion = Assembly.GetEntryAssembly().GetName().Version; //create an assembly version from the downloaded version text file Version updateVersion = new Version(textUpdateVersion); //if downloaded version is higher than our current version then request to download new assembly if (updateVersion > currentVersion) { //prompt user to commence update DialogResult result = MessageBox.Show($"Would you like to update to the latest version {updateVersion}?", Properties.Resources.AppName, MessageBoxButtons.YesNo); if (result == DialogResult.Yes) { //get update file metadata getRequest = service.Files.Get(updateFileID); //download update file to memory await using var ms2 = new MemoryStream(); await getRequest.DownloadAsync(ms2); //***ms2 is always empty here*** //convert file to binary ms2.Position = 0; var br = new BinaryReader(ms2); byte[] bin = br.ReadBytes(Convert.ToInt32(ms2.Length)); //rest of code } } } catch { //deal with any exceptions } } }
排查与解决建议
- 验证文件权限与ID:确认Update.exe的文件ID完全正确,且该文件已明确共享给服务账号的邮箱地址,权限至少设为“查看”(下载需要此权限)。
- 修正异步方法签名:将
async static void CheckForUpdate()改为async static Task CheckForUpdate(),调用时使用await GoogleDriveAccess.CheckForUpdate();。async void会导致异步操作未完成就继续执行后续代码,可能出现流未写入就读取的情况。 - 添加异常详情捕获:把空的catch块改为捕获具体异常并输出详情,比如:
这能快速定位是权限问题、API调用错误还是文件不存在等问题。catch (Exception ex) { MessageBox.Show($"更新出错:{ex.Message}\n{ex.StackTrace}"); } - 检查API作用域:确认使用的Scope是
DriveService.Scope.DriveReadonly(只读权限足够下载文件)或DriveService.Scope.Drive,避免权限不足导致下载失败。 - 下载前验证流状态:在操作ms2前先判断
ms2.Length是否大于0,若为0则直接提示下载失败,避免后续无效操作:await getRequest.DownloadAsync(ms2); if (ms2.Length == 0) { MessageBox.Show("更新文件下载失败,流为空"); return; } ms2.Position = 0; //后续二进制读取代码
内容的提问来源于stack exchange,提问作者Deolus
相关产品推荐
相关产品推荐

