批量文件下载 - Drive API .NET

时间:2016-09-27 23:39:54

标签: c# .net google-drive-api

问题:

如何告诉我的备份工具下载它在fileids中记录的所有文件?

我使用的方法是C#/。NET https://developers.google.com/drive/v3/web/manage-downloads#examples

我将免费提供无聊的详细信息,并说我的程序的一部分以每个用户(好吧,使用Apps Service API)登录一次,抓取他们的所有文件' fileIds并将它们记录到平面文本文件中。我的程序然后打开该平面文本文件并开始下载为该用户记录的每个fileId,但问题是:它太慢了,因为它为文件打开一个新连接,等待文件完成,然后得到一个新的fileid并重新开始整个过程​​。效率不高。

谷歌的例子,我几乎复制了Verbatim(我通过立即抓取并导出他们的mimetype来修改vars一点,所以前三行是没有意义的):

var fileId = "0BwwA4oUTeiV1UVNwOHItT0xfa2M";
var request = driveService.Files.Get(fileId);
var stream = new System.IO.MemoryStream();

// Add a handler which will be notified on progress changes.
// It will notify on each chunk download and when the
// download is completed or failed.
request.MediaDownloader.ProgressChanged +=
    (IDownloadProgress progress) =>
{
    switch(progress.Status)
    {
        case DownloadStatus.Downloading:
        {
            Console.WriteLine(progress.BytesDownloaded);
            break;
        }
        case DownloadStatus.Completed:
        {
            Console.WriteLine("Download complete.");
            break;
        }
        case DownloadStatus.Failed:
        {
            Console.WriteLine("Download failed.");
            break;
        }
    }
};
request.Download(stream);

有没有什么方法可以简化这一点,以便我的程序可以在一次大握手中下载它为用户知道的所有文件,而不是单独读取fileid,然后打开会话,导出,下载,关闭,然后执行下一个文件完全相同的东西?希望这是有道理的。

提前感谢您提供任何帮助!

- 麦克

--- --- EDIT

我想添加更多详细信息,以便我希望我做的更有意义:

以下代码中发生的事情是:我正在创建一个"请求"这将让我导出文件类型(我从平面文本文件中导出为fileId [0],以及" mimetype"它在数组中作为fileId [1]。) 什么杀死程序的速度是必须建立" BuildService"每次请求每个文件。

foreach (var file in deltafiles)
{
    try
    {
    if (bgW.CancellationPending)
    {
        stripLabel.Text = "Backup canceled!";
        e.Cancel = true;
        break;
        }
        DateTime dt = DateTime.Now;
        string[] foldervalues = File.ReadAllLines(savelocation + "folderlog.txt");
        cnttototal++;
        bgW.ReportProgress(cnttototal);
        // Our file is a CSV. Column 1 = file ID, Column 2 = File name
        var values = file.Split(',');

        string fileId = values[0];
        string fileName = values[1];
        string mimetype = values[2];
        mimetype = mimetype.Replace(",", "_");
        string folder = values[3];
        int foundmatch = 0;
        int folderfilelen = foldervalues.Count();

        fileName = fileName.Replace('\\', '_').Replace('/', '_').Replace(':', '_').Replace('!', '_').Replace('\'', '_').Replace('*', '_').Replace('#', '_').Replace('[', '_').Replace(']', '_');

        var request = CreateService.BuildService(user).Files.Export(fileId, mimetype);

        //Default extensions for files. Not sure what this should be, so we'll null it for now.
        string ext = null;

        // Things get sloppy here. The reason we're checking MimeTypes
        // is because we have to export the files from Google's format
        // to a format that is readable by a desktop computer program
        // So for example, the google-apps.spreadsheet will become an MS Excel file.
        if (mimetype == mimeSheet || mimetype == mimeSheetRitz || mimetype == mimeSheetml)
        {
            request = CreateService.BuildService(user).Files.Export(fileId, exportSheet);
            ext = ".xls";
        }
        if (mimetype == mimeDoc || mimetype == mimeDocKix || mimetype == mimeDocWord)
        {
            request = CreateService.BuildService(user).Files.Export(fileId, exportDoc);
            ext = ".docx";
        }
        if (mimetype == mimePres || mimetype == mimePresPunch)
        {
            request = CreateService.BuildService(user).Files.Export(fileId, exportPres);
            ext = ".ppt";
        }
        if (mimetype == mimeForm || mimetype == mimeFormfb || mimetype == mimeFormDrawing)
        {
            request = CreateService.BuildService(user).Files.Export(fileId, exportForm);
            ext = ".docx";
        }
        // Any other file type, assume as know what it is (which in our case, will be a txt file)
        // apply the mime type and carry on.
        string dest = Path.Combine(savelocation, fileName + ext);
        var stream = new System.IO.FileStream(dest, FileMode.Create, FileAccess.ReadWrite);
        int oops = 0;
        // Add a handler which will be notified on progress changes.
        // It will notify on each chunk download and when the
        // download is completed or failed.

        request.MediaDownloader.ProgressChanged +=
        (IDownloadProgress progress) =>
        {
            switch (progress.Status)
            {
                case DownloadStatus.Downloading:
                {
                    throw new Exception("File may be corrupted.");
                    break;
                    }
                case DownloadStatus.Completed:
                {
                    Console.WriteLine("Download complete.");
                    break;
                }
                case DownloadStatus.Failed:
                {
                    oops = 1;
                    logFile.WriteLine(fileName + " could not be downloaded. Possible Google draw/form OR bad name.\n");
                    break;
                }
            }
        };
        request.Download(stream);
        stream.Close();
        stream.Dispose();

有什么方法可以简化这个过程,所以每次我想下载文件时都不需要构建驱动器服务吗?程序读取的平面文本文件看起来类似于

FILEID,实际文件名,MIMETYPE

那么有什么方法可以让中间人切断并提供请求。下载方法没有经常提醒" foreach"语句将文件类型导出为文件系统可读文件? (好抱怨,对不起,我知道这听起来很多。)

任何指针都会很棒!!

2 个答案:

答案 0 :(得分:0)

您可能想要尝试教程:Google Drive API with C# .net – Download。这是一个更简单的代码来下载文件。还有其他因素,如间歇性互联网连接,可能会影响下载文件的ETA。

代码示例:

/// Download a file
/// Documentation: https://developers.google.com/drive/v2/reference/files/get
/// 

/// a Valid authenticated DriveService
/// File resource of the file to download
/// location of where to save the file including the file name to save it as.
/// 
public static Boolean downloadFile(DriveService _service, File _fileResource, string _saveTo)
{

if (!String.IsNullOrEmpty(_fileResource.DownloadUrl))
{
try
{
var x = _service.HttpClient.GetByteArrayAsync(_fileResource.DownloadUrl );
byte[] arrBytes = x.Result;
System.IO.File.WriteAllBytes(_saveTo, arrBytes);
return true; 
}
catch (Exception e)
{
Console.WriteLine("An error occurred: " + e.Message);
return false;
}
}
else
{
// The file doesn't have any content stored on Drive.
return false;
}
}
  

使用_service.HttpClient.GetByteArrayAsync我们可以传递我们想要下载的文件的下载URL。下载文件后,只需将文件转发到磁盘即可。

希望这有帮助!

答案 1 :(得分:0)

这不是一个答案,就像它是一个解决方案一样,即便如此,它只是答案的一半(现在。)我把手套脱掉并且玩得很脏。

首先,我将我的nuget google api软件包更新到我的VS项目中的最新版本,然后转到https://github.com/google/google-api-dotnet-client,分叉/克隆它,更改了Google.Apis.Drive.v3.cs文件(编译为google.apis.drive.v3.dll),以便mimetype不再是只读的(它可以执行;并设置;,默认情况下,只允许获取)。

因为我已经知道了mime类型,所以我现在可以强制将mime类型分配给请求并继续我的生活,而不是必须构建客户端服务,连接,只导出我的文件类型已经知道了。

它不漂亮,不应该怎么做,但这真的很困扰我!

回到Mr.Rebot,我再次感谢你的帮助和研究! : - )