Google Drive. Refresh authorization token while a

2019-04-12 08:59发布

问题:

What is the way to refresh authorization token while a large file is uploading to Google Drive? For example: expiration time of the current authorization token is "06:00 AM". The file uploading started at "05:15 AM". So at "06:00 AM" the application get exception due authorization token is invalid.

I've tried to around the issue with the below source code, but it does not work.

/// <summary>
/// Uploads a file with a specified path.
/// </summary>
/// <param name="startFolder">The start folder.</param>
/// <param name="path">The path of destination file.</param>
/// <param name="localFile">The local file to upload.</param>
/// <returns>The uploaded file.</returns>
private File GdUploadFile(File startFolder, string path, FileInfo localFile)
{
    if (startFolder == null)
    {
        throw new ArgumentNullException("startFolder");
    }

    if (localFile == null)
    {
        throw new ArgumentNullException("localFile");
    }

    if (!localFile.Exists)
    {
        throw new FileNotFoundException("File not found", localFile.FullName);
    }

    var config = GetConfiguration();

    if (config.TraceLog)
    {
        Destination.Logger.LogDebug(string.Format("{0} \tUpload file \"{1}\" to \"{2}\"", Destination.Name, localFile.FullName, path));
    }

    string pathToFile = string.IsNullOrEmpty(path) ? localFile.Name : path;

    string remotePath = ExtractFilePath(pathToFile);
    var fileFolder = GdCreateFolderByPath(startFolder, remotePath);
    var fileName = ExtractFileName(pathToFile);

    DriveService service = GetDriveService();

    var body = new File
                   {
                       Title = fileName,
                       Description = "My File",
                       MimeType = BackupFileMimeType,
                       Kind = DriveFileKindType,
                       OriginalFilename = fileName,
                       FileExtension = localFile.Extension,
                       Parents = new List<ParentReference>
                                     {
                                         new ParentReference
                                             {
                                                 ETag = fileFolder.ETag,
                                                 Id = fileFolder.Id,
                                                 Kind = fileFolder.Kind
                                             }
                                     }
                   };

    FilesResource.InsertMediaUpload request;
    var source = new MediaFileSource(localFile.FullName, BackupFileMimeType);

    using (var fileStream = source.GetDataStream())
    {
        if (config.TraceLog)
        {
            Destination.Logger.LogDebug(string.Format("{0} \tUploading \"{1}\"...", Destination.Name, localFile.FullName));
        }

        request = service.Files.Insert(body, fileStream, body.MimeType);

        if (config.TraceLog)
        {
            int postedPercent = 0;

            request.ProgressChanged += p =>
                                           {
                                               var currentPercent = (int) (p.BytesSent/(double) source.ContentLength*100);

                                               if (currentPercent != postedPercent)
                                               {
                                                   string msg = string.Format("{0} \tPosted {1}% ({2} bytes)", Destination.Name,
                                                                              currentPercent, p.BytesSent);
                                                   Destination.Logger.LogDebug(msg);
                                                   postedPercent = currentPercent;
                                               }
                                           };
        }

        var connection = Destination.Connection as GoogleDriveDestinationConnection;
        Debug.Assert(connection != null, "connection != null");

        request.ProgressChanged += p =>
                                       {
                                           bool refreshAuth = connection.ForceRefreshAuthorization();
                                           var auth =
                                               request.Authenticator as
                                               Google.Apis.Authentication.OAuth2.OAuth2Authenticator<NativeApplicationClient>;

                                           if (auth != null && auth.State != null && refreshAuth)
                                           {
                                               var state = connection.AuthorizationState;
                                               auth.State.AccessToken = state.AccessToken;
                                               auth.State.AccessTokenExpirationUtc = state.AccessTokenExpirationUtc;
                                               auth.State.AccessTokenIssueDateUtc = state.AccessTokenIssueDateUtc;
                                               auth.State.Callback = state.Callback;
                                               auth.State.RefreshToken = state.RefreshToken;
                                               auth.State.SaveChanges();

                                               if (config.TraceLog)
                                               {
                                                   Destination.Logger.LogDebug("Authorization state for the upload request is updated");
                                               }

                                           }
                                       };

        request.ChunkSize = ChunkSize;
        request.Upload();

        if (config.TraceLog)
        {
            Destination.Logger.LogDebug(string.Format("{0} \t\"{1}\" uploaded", Destination.Name, localFile.FullName));
        }
    }

    return request.ResponseBody;
}

回答1:

Consider doing Resumable upload (https://developers.google.com/drive/manage-uploads#resumable). Refresh the token when needed and continue the upload where you left off.



回答2:

I was not able to find a satisfactory solution to the problem of invalid authorization token. So I have created my own open source lightweight library for working with files on Google Drive. The library invokes all REST functions directly and have full control over uploading or downloading processes. It resolves the problem by refreshing the authorization token every hour. The library is currently in use in thousands of installations of my company’s Sql Server backup product, it is very stable and has successfully resolved this problem. You can take the source code and examples from here: https://github.com/AlexeyVlg/Pranas.Net.Clouds