C# - Leer un documento de texto en Gmail

Iniciado por TickTack, 19 Septiembre 2017, 18:51 PM

0 Miembros y 1 Visitante están viendo este tema.

TickTack

Hola,

hay una forma de que se pueda programar leer el contenido de este documento de texto: https://drive.google.com/file/d/0B04WDU5Df8zYN2NxMlRlMlhYbm8/view?usp=sharing


Gracias y saludos
Citar
"Ninguna mentira puede inventarse lo suficientemente patán: el pueblo hispanohablante la cree. Por una consigna que se les dio, persiguieron a sus compatriotas con mayor encarnizamiento que a sus verdaderos enemigos."

Eleкtro

#1
Hola TickTack.

Bueno, hay dos maneras.

La primera y más sencilla sería suficiente con adaptar la url:

Código (csharp) [Seleccionar]
Uri uri = new Uri("https://drive.google.com/uc?export=download&id=0B04WDU5Df8zYN2NxMlRlMlhYbm8");

using (WebClient wc = new WebClient()) {
   string content = wc.DownloadString(uri);
}


Si eso para ti te es suficiente, entonces no hay necesidad de que sigas leyendo aquí abajo.






La segunda manera, suponiendo que el documento esté almacenado en tu cuenta personal de Google Drive, es decir, si eres el propietario y/o es de otro usuario pero lo tienes compartido DENTRO de tu cuenta y quieres administrar el archivo de forma avanzada y obtener control total sobre tus acciones, entonces la solución más sofisticada sería utilizar la API de Google Drive para .NET.

Paquete NuGet:

Documentación y samples:




Aquí te dejo un cliente que escribí de la API Google Drive v3 para administrar archivos (listar, descargar, subir, reemplazar, eliminar) en nuestra propia cuenta.

El código es un extracto reducido de mi framework comercial ElektroKit, el cual se puede usar tanto desde C# como VB.NET. Tan solo he dejado los miembros necesarios para la autentificación, enumeración de archivos y directorios, y descarga de archivos.

Si alguien desea obtener más información con respecto a ElektroKit Framework, les invito a mirar mi firma de usuario aquí abajo del todo de mi post.

Espero que esto le sirva de ayuda a alguien, aparte de los samples oficiales de Google.

PD: Me sabe mal recortar tanto el código, pero además el foro tiene un límite de caracteres muy corto y no cabe ni un cacho.

Código (vbnet) [Seleccionar]
' ***********************************************************************
' Author   : Elektro
' Modified : 22-July-2017
' ***********************************************************************

#Region " Drive Scopes "
Namespace ElektroKit.ThirdParty.Google.Drive.Enums
   ''' <summary>
   ''' Specifies the OAuthv2 scopes for use with the Google Drive API.
   ''' </summary>
   <Flags>
   Public Enum DriveScopes As Integer

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive"/> scope.
       ''' <para></para>
       ''' View and manage the files in your Google Drive.
       ''' </summary>
       Full = 2

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive.appfolder"/> scope.
       ''' <para></para>
       ''' View and manage its own configuration data in your Google Drive.
       ''' </summary>
       ApplicationData = 4

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive.file"/> scope.
       ''' <para></para>
       ''' View and manage Google Drive files and folders that you have opened or created with this application.
       ''' </summary>
       Files = 8

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive.metadata"/> scope.
       ''' <para></para>
       ''' View and manage metadata of files in your Google Drive.
       ''' </summary>
       Metadata = 16

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive.scripts"/> scope.
       ''' <para></para>
       ''' Modify your Google Apps Script scripts' behavior.
       ''' </summary>
       Scripts = 32

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive.readonly"/> scope.
       ''' <para></para>
       ''' View the files in your Google Drive.
       ''' </summary>
       [ReadOnly] = 64

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive.metadata.readonly"/> scope.
       ''' <para></para>
       ''' View metadata for files in your Google Drive.
       ''' </summary>
       MetadataReadonly = 128

       ''' <summary>
       ''' Reffers to the <see href="https://www.googleapis.com/auth/drive.photos.readonly"/> scope.
       ''' <para></para>
       ''' View the photos, videos and albums in your Google Photos.
       ''' </summary>
       PhotosReadonly = 256

   End Enum
End Namespace
#End Region


+

Código (vbnet) [Seleccionar]
[code=vbnet]' ***********************************************************************
' Author   : Elektro
' Modified : 22-July-2017
' ***********************************************************************

#Region " Imports "

Imports System.IO
Imports System.Threading
Imports System.Threading.Tasks

Imports ElektroKit.ThirdParty.Google.Drive.Enums

' #If NET45 OrElse NET46 Then

Imports Google.Apis.Auth.OAuth2
Imports Google.Apis.Download
Imports Google.Apis.Drive.v3
Imports Google.Apis.Drive.v3.Data
Imports Google.Apis.Services
Imports Google.Apis.Upload
Imports Google.Apis.Util.Store

' #End If

#End Region

#Region " Drive Client "

Namespace ElektroKit.ThirdParty.Google.Drive.Types

' #If NET45 OrElse NET46 Then

    ''' <summary>
    ''' A client for Google Drive service.
    ''' </summary>
    Public NotInheritable Class DriveClient : Implements IDisposable

#Region " Private Fields "

dim demoMessage as string = "Buy ElektroKit Framework to have access to the full version."

        ''' <summary>
        ''' The Google Drive service client.
        ''' </summary>
        Private client As DriveService

        ''' <summary>
        ''' OAuthv2 credential for accessing protected resources using an access token,
        ''' as well as optionally refreshing the access token when it expires using a refresh token.
        ''' </summary>
        Private credential As UserCredential

        ''' <summary>
        ''' A message for an exception that will be thrown when the user has not authorized the app.
        ''' </summary>
        Private ReadOnly authExceptionMessage As String =
            "The user has not yet authorized the usage of this application.
             Call 'DriveClient.Authorize()' or 'DriveClient.AuthorizeAsync()' methods."

        ''' <summary>
        ''' The Google Drive OAuthv2 scope urls.
        ''' </summary>
        Private scopeDict As New Dictionary(Of DriveScopes, String)(StringComparison.Ordinal) From
        {
            {DriveScopes.Full, DriveService.Scope.Drive},
            {DriveScopes.ApplicationData, DriveService.Scope.DriveAppdata},
            {DriveScopes.Files, DriveService.Scope.DriveFile},
            {DriveScopes.Metadata, DriveService.Scope.DriveMetadata},
            {DriveScopes.MetadataReadonly, DriveService.Scope.DriveMetadataReadonly},
            {DriveScopes.PhotosReadonly, DriveService.Scope.DrivePhotosReadonly},
            {DriveScopes.ReadOnly, DriveService.Scope.DriveReadonly},
            {DriveScopes.Scripts, DriveService.Scope.DriveScripts}
        }

#End Region

#Region " Properties "

        ''' <summary>
        ''' Gets the client credentials.
        ''' </summary>
        ''' <value>
        ''' The client credentials.
        ''' </value>
        Public ReadOnly Property Secrets As ClientSecrets

        ''' <summary>
        ''' Gets the mail address to authorize Drive service. (e.g: "yourmail@gmail.com")
        ''' </summary>
        ''' <value>
        ''' The mail address to authorize Drive service. (e.g: "yourmail@gmail.com")
        ''' </value>
        Public ReadOnly Property MailAddress As String

        ''' <summary>
        ''' Gets the current Drive OAuthv2 scopes.
        ''' </summary>
        ''' <value>
        ''' The current Drive OAuthv2 scopes.
        ''' </value>
        Public ReadOnly Property Scope As DriveScopes

        ''' <summary>
        ''' Gets a value that determines whether Google Drive API authorization was done.
        ''' </summary>
        ''' <value>
        ''' A value that determines whether Google Drive API authorization was done.
        ''' </value>
        Public ReadOnly Property IsAuthorized As Boolean
            Get
                Return Me.isAuthorizedB
            End Get
        End Property
        ''' <summary>
        ''' ( Backing field )
        ''' A value that determines whether Google Drive API authorization was done.
        ''' </summary>
        Private isAuthorizedB As Boolean = False

#End Region

#Region " Constructors "

        Private Sub New()
        End Sub

        ''' <summary>
        ''' Initializes a new instance of the <see cref="DriveClient"/> class.
        ''' </summary>
        ''' <param name="apiFile">
        ''' The <c>client_secrets.json</c> file generated by Drive API console that contains the OAuthv2 login data
        ''' such as the client id, client secret, and redirection URI.
        ''' </param>
        ''' <param name="mailAddress">
        ''' The mail address to authorize Drive service. (e.g: "yourmail@gmail.com")
        ''' </param>
        ''' <param name="scopes">
        ''' The Drive OAuthv2 scope.
        ''' </param>
        Public Sub New(apiFile As String, mailAddress As String, scopes As DriveScopes)
            Me.MailAddress = mailAddress
            Me.Scope = scopes

            Using stream As FileStream = New FileInfo(apiFile).OpenRead()
                Me.Secrets = GoogleClientSecrets.Load(stream).Secrets
            End Using
        End Sub

#End Region

#Region " Public Methods "

#Region " Authorization "

        ''' <summary>
        ''' Authorizes this instance to use Google Drive API services.
        ''' </summary>
        ''' <example>
        ''' <code>
        ''' Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        ''' Dim credential As UserCredential = client.Authorize()
        ''' </code>
        ''' </example>
        <DebuggerStepThrough>
        Public Function Authorize() As UserCredential
            Dim t As Task(Of UserCredential) = Task.Run(AddressOf Me.AuthorizeAsync)
            t.Wait(Timeout.Infinite)
            Return t.Result
        End Function

        ''' <summary>
        ''' Authorizes this instance to use Google Drive API services.
        ''' </summary>
        ''' <example>
        ''' <code>
        ''' Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        ''' Dim credential As UserCredential = Await client.AuthorizeAsync()
        ''' </code>
        ''' </example>
        Public Async Function AuthorizeAsync() As Task(Of UserCredential)

            Dim scopeUrls As String() = Me.GetScopeUrls(Me.Scope)

            Me.credential =
                 Await GoogleWebAuthorizationBroker.AuthorizeAsync(Me.Secrets,
                                                                   scopeUrls.ToArray(),
                                                                   Me.MailAddress,
                                                                   CancellationToken.None,
                                                                   New FileDataStore("Test_Name", fullPath:=False))

            Me.client = New DriveService(New BaseClientService.Initializer() With {
                                         .HttpClientInitializer = Me.credential,
                                         .ApplicationName = "Test_Name"
            })

            Me.isAuthorizedB = True
            Return Me.credential

        End Function

#End Region

#Region " Get Files "

        ''' <summary>
        ''' Gets all the files stored in the current user account.
        ''' </summary>
        ''' <example>
        ''' <code>
        '''     Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        '''     Dim credential As UserCredential = client.Authorize()
        '''     Dim files As List(Of Data.File) = client.GetFiles()
        '''     Dim fileCount As Integer
        '''
        '''     For Each file As Data.File In files
        '''         Dim sb As New Global.System.Text.StringBuilder()
        '''         With sb
        '''             .AppendLine(String.Format("Id: {0}", file.Id))
        '''             .AppendLine(String.Format("Name: {0}", file.Name))
        '''             .AppendLine(String.Format("Url: {0}", If(file.WebContentLink, file.WebViewLink)))
        '''         End With
        '''         Console.WriteLine(sb.ToString())
        '''     Next file
        ''' </code>
        ''' </example>
        <DebuggerStepThrough>
        Public Function GetFiles() As List(Of Data.File)

            If Not (Me.isAuthorizedB) Then
                Throw New InvalidOperationException(Me.authExceptionMessage)

            Else
                Dim t As Task(Of List(Of Data.File)) = Task.Run(AddressOf Me.GetFilesAsync)
                t.Wait(Timeout.Infinite)
                Return t.Result

            End If

        End Function

        Public Function GetFiles(predicate As Func(Of Data.File, Boolean)) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        ''' <summary>
        ''' Asynchronously gets all the files stored in the current user account.
        ''' </summary>
        ''' <example>
        ''' <code>
        '''     Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        '''     Dim credential As UserCredential = Await client.AuthorizeAsync()
        '''     Dim files As List(Of Data.File) = Await client.GetFilesAsync()
        '''     Dim fileCount As Integer
        '''
        '''     For Each file As Data.File In files
        '''         Dim sb As New Global.System.Text.StringBuilder()
        '''         With sb
        '''             .AppendLine(String.Format("Id: {0}", file.Id))
        '''             .AppendLine(String.Format("Name: {0}", file.Name))
        '''             .AppendLine(String.Format("Url: {0}", If(file.WebContentLink, file.WebViewLink)))
        '''         End With
        '''         Console.WriteLine(sb.ToString())
        '''     Next file
        ''' </code>
        ''' </example>
        <DebuggerStepThrough>
        Public Async Function GetFilesAsync() As Task(Of List(Of Data.File))

            If Not (Me.isAuthorizedB) Then
                Throw New InvalidOperationException(Me.authExceptionMessage)

            Else
                Dim request As FilesResource.ListRequest = Me.client.Files.List()
                With request
                    .PageSize = 100
                    .IncludeTeamDriveItems = False
                    .SupportsTeamDrives = False
                    .Fields = "nextPageToken, files"
                    .Q = "not mimeType contains 'folder'"
                End With

                Dim response As FileList = Await request.ExecuteAsync()

                Dim files As New List(Of Data.File)
                Do While True

                    For Each file As Data.File In response.Files
                        Dim getRequest As FilesResource.GetRequest = Me.client.Files.Get(file.Id)
                        With getRequest
                            .SupportsTeamDrives = False
                            .Fields = "*"
                        End With

                        Dim getResponse As Data.File = Await getRequest.ExecuteAsync()
                        getRequest.AcknowledgeAbuse = True
                        files.Add(getResponse)
                    Next file

                    If Not String.IsNullOrEmpty(response.NextPageToken) Then
                        request.PageToken = response.NextPageToken
                        response = Await request.ExecuteAsync()
                    Else
                        Exit Do
                    End If

                Loop

                Return files

            End If

        End Function

        Public Async Function GetFilesAsync(predicate As Func(Of Data.File, Boolean)) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        ''' <summary>
        ''' Gets a file stored in the current user account that matches the specified file id.
        ''' </summary>
        ''' <example>
        ''' <code>
        '''     Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        '''     Dim credential As UserCredential = client.Authorize()
        '''     Dim file As Data.File) = client.GetFileById(" File Id. ")
        '''
        '''     Dim sb As New Global.System.Text.StringBuilder()
        '''     With sb
        '''          .AppendLine(String.Format("Id: {0}", file.Id))
        '''          .AppendLine(String.Format("Name: {0}", file.Name))
        '''          .AppendLine(String.Format("Url: {0}", If(file.WebContentLink, file.WebViewLink)))
        '''     End With
        '''     Console.WriteLine(sb.ToString())
        ''' </code>
        ''' </example>
        <DebuggerStepThrough>
        Public Function GetFileById(id As String) As Data.File
            If Not (Me.isAuthorizedB) Then
                Throw New InvalidOperationException(Me.authExceptionMessage)

            Else
                Dim t As Task(Of Data.File) = Task.Run(Function() Me.GetFileByIdAsync(id))
                t.Wait(Timeout.Infinite)
                Return t.Result

            End If
        End Function

        Public Async Function GetFileByIdAsync(id As String) As Task(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetFilesByName(displayName As String) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetFilesByNameAsync(displayName As String) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetOwnedFiles() As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetOwnedFiles(predicate As Func(Of Data.File, Boolean)) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFilesAsync() As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFilesAsync(predicate As Func(Of Data.File, Boolean)) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetOwnedFilesByName(displayName As String) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFilesByNameAsync(displayName As String) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetOwnedFileById(id As String) As Data.File
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFileByIdAsync(id As String) As Task(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#Region " Get Folders "

        Public Function GetFolders() As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetFolders(predicate As Func(Of Data.File, Boolean)) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetFoldersAsync() As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetFoldersAsync(predicate As Func(Of Data.File, Boolean)) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetFolderById(id As String) As Data.File
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetFolderByIdAsync(id As String) As Task(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetFoldersByName(displayName As String) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetFoldersByNameAsync(displayName As String) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetOwnedFolders() As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetOwnedFolders(predicate As Func(Of Data.File, Boolean)) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFoldersAsync() As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFoldersAsync(predicate As Func(Of Data.File, Boolean)) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function GetOwnedFoldersByName(displayName As String) As List(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFoldersByNameAsync(displayName As String) As Task(Of List(Of Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function
        Public Function GetOwnedFolderById(id As String) As Data.File
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function GetOwnedFolderByIdAsync(id As String) As Task(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#Region " Download File "

        Public Sub DownloadFile(srcFile As Data.File,dstFilePath As String)
             'Buy ElektroKit Framework to have access to this member.
        End Sub

        ''' <summary>
        ''' Downloads the specified file.
        ''' </summary>
        ''' <example>
        ''' <code>
        ''' Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        ''' Dim credential As UserCredential = client.Authorize()
        ''' Dim url As String = "https://drive.google.com/uc?export=download&amp;id=1B04WDF5Df8zYN2NXMlRlMlhYbm8"
        '''         
        ''' client.DownloadFile(url, dstFile)
        ''' </code>
        ''' </example>
        ''' <param name="url">
        ''' A Google Drive url that points to the file to download.
        ''' </param>
        '''
        ''' <param name="dstFilePath">
        ''' The destination file path where to save the downloaded file.
        ''' </param>
        <DebuggerStepThrough>
        Public Sub DownloadFile(url As String,
                                dstFilePath As String)

            If Not (Me.isAuthorizedB) Then
                Throw New InvalidOperationException(Me.authExceptionMessage)

            Else
                Dim t As Task(Of IDownloadProgress) =
                    Task.Run(Function() Me.DownloadFileAsync(url, dstFilePath, Nothing, Nothing))
                t.Wait(Timeout.Infinite)

                If (t.Result.Status = DownloadStatus.Failed) Then
                    Throw t.Result.Exception
                End If

            End If

        End Sub

        Public Sub DownloadFile(uri As Uri,dstFilePath As String)
             'Buy ElektroKit Framework to have access to this member.
        End Sub

        Public Async Function DownloadFileAsync(srcFile As Data.File,dstFilePath As String) As Task(Of IDownloadProgress)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        ''' <summary>
        ''' Asynchronously downloads the specified file.
        ''' </summary>
        ''' <example>
        ''' <code>
        ''' Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        ''' Dim credential As UserCredential = Await client.AuthorizeAsync()
        ''' Dim url As String = "https://drive.google.com/uc?export=download&amp;id=1B04WDF5Df8zYN2NXMlRlMlhYbm8"
        '''         
        ''' Dim progress As IDownloadProgress = Await client.DownloadFileAsync(url, dstFile)
        ''' Dim status As DownloadStatus = progress.Status
        ''' Console.WriteLine(status)
        ''' </code>
        ''' </example>
        ''' <param name="url">
        ''' A Google Drive url that points to the file to download.
        ''' </param>
        '''
        ''' <param name="dstFilePath">
        ''' The destination file path where to save the downloaded file.
        ''' </param>
        Public Async Function DownloadFileAsync(url As String,
                                                dstFilePath As String) As Task(Of IDownloadProgress)

            Return Await Me.DownloadFileAsync(url, dstFilePath, Nothing, Nothing)

        End Function

        Public Async Function DownloadFileAsync(uri As Uri,dstFilePath As String) As Task(Of IDownloadProgress)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function DownloadFileAsync(srcFile As Data.File,dstFilePath As String,progressHandler As Action(Of IDownloadProgress),cancellationToken As CancellationToken) As Task(Of IDownloadProgress)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        ''' <summary>
        ''' Asynchronously downloads the specified file.
        ''' </summary>
        ''' <example>
        ''' <code>
        ''' Dim client As New DriveClient("C:\GoogleSecrets.json", "yourmail@gmail.com", DriveScopes.Full)
        ''' Dim credential As UserCredential = Await client.AuthorizeAsync()
        ''' Dim url As String = "https://drive.google.com/uc?export=download&amp;id=1B04WDF5Df8zYN2NXMlRlMlhYbm8"
        '''         
        ''' Dim progress As IDownloadProgress =
        '''     Await client.DownloadFileAsync(url, dstFile, AddressOf Me.Download_ProgressChanged, Nothing)
        '''
        ''' Public Sub Download_ProgressChanged(e As IDownloadProgress)
        '''
        '''     Select Case e.Status
        '''
        '''         Case DownloadStatus.Downloading
        '''             Console.WriteLine("Bytes downloaded: {0}", e.BytesDownloaded)
        '''
        '''         Case DownloadStatus.Completed
        '''             Console.WriteLine("Download completed.")
        '''
        '''         Case DownloadStatus.Failed
        '''             Console.WriteLine("Download failed. Reason: {0}", e.Exception.Message)
        '''
        '''     End Select
        '''
        ''' End Sub
        ''' </code>
        ''' </example>
        ''' <param name="url">
        ''' A Google Drive url that points to the file to download.
        ''' </param>
        '''
        ''' <param name="dstFilePath">
        ''' The destination file path where to save the downloaded file.
        ''' </param>
        '''
        ''' <param name="progressHandler">
        ''' A event handler that will receive progress changes of the download operation.
        ''' </param>
        '''
        ''' <param name="cancellationToken">
        ''' A cancellation token to cancel the download operation.
        ''' </param>
        Public Async Function DownloadFileAsync(url As String,
                                                dstFilePath As String,
                                                progressHandler As Action(Of IDownloadProgress),
                                                cancellationToken As CancellationToken) As Task(Of IDownloadProgress)

            If Not (Me.isAuthorizedB) Then
                Throw New InvalidOperationException(Me.authExceptionMessage)

            Else
                Dim downloader As New MediaDownloader(Me.client)
                ' downloader.ChunkSize = 262144

                Dim progress As IDownloadProgress
                Using fs As New FileStream(dstFilePath, FileMode.Create, FileAccess.Write, FileShare.Read)
                    AddHandler downloader.ProgressChanged, progressHandler
                    progress = Await downloader.DownloadAsync(url, fs)
                    RemoveHandler downloader.ProgressChanged, progressHandler
                End Using

                Return progress

            End If

        End Function

        Public Async Function DownloadFileAsync(uri As Uri,dstFilePath As String,progressHandler As Action(Of IDownloadProgress),cancellationToken As CancellationToken) As Task(Of IDownloadProgress)
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#Region " Upload File "

        Public Function UploadFile(srcFile As FileInfo,ParamArray parentFolderIds As String()) As KeyValuePair(Of ResumableUpload, Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function UploadFile(srcFile As FileInfo,dstFile As Data.File,ParamArray parentFolderIds As String()) As KeyValuePair(Of ResumableUpload, Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function UploadFileAsync(srcFile As FileInfo,progressHandler As Action(Of IUploadProgress),cancellationToken As CancellationToken,ParamArray parentFolderIds As String()) As Task(Of KeyValuePair(Of ResumableUpload, Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function UploadFileAsync(srcFile As FileInfo,dstFile As Data.File,progressHandler As Action(Of IUploadProgress),cancellationToken As CancellationToken,ParamArray parentFolderIds As String()) As Task(Of KeyValuePair(Of ResumableUpload, Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#Region " Update (replace) File "

        Public Function UpdateFile(srcFile As FileInfo,dstFile As Data.File) As KeyValuePair(Of ResumableUpload, Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function UpdateFile(srcFile As FileInfo,dstFileId As String) As KeyValuePair(Of ResumableUpload, Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function UpdateFileAsync(srcFile As FileInfo,dstFile As Data.File,progressHandler As Action(Of IUploadProgress),cancellationToken As CancellationToken) As Task(Of KeyValuePair(Of ResumableUpload, Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function UpdateFileAsync(srcFile As FileInfo,dstFileId As String,progressHandler As Action(Of IUploadProgress),cancellationToken As CancellationToken) As Task(Of KeyValuePair(Of ResumableUpload, Data.File))
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#Region " Create Folder "

        Public Function CreateFolder(dstName As String, ParamArray parentFolderIds As String()) As Data.File
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function CreateFolderAsync(dstName As String, ParamArray parentFolderIds As String()) As Task(Of Data.File)
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#Region " Delete File "

        Public Function DeleteFile(file As Data.File) As String
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function DeleteFile(fileId As String) As String
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function DeleteFileAsync(file As Data.File) As Task(Of String)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function DeleteFileAsync(fileId As String) As Task(Of String)
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#Region " Delete Folder "

        Public Function DeleteFolder(folder As Data.File) As String
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Function DeleteFolder(folderId As String) As String
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function DeleteFolderAsync(folder As Data.File) As Task(Of String)
             'Buy ElektroKit Framework to have access to this member.
        End Function

        Public Async Function DeleteFolderAsync(folderId As String) As Task(Of String)
             'Buy ElektroKit Framework to have access to this member.
        End Function

#End Region

#End Region

#Region " Private Methods "
        Private Function GetScopeUrls(scopes As DriveScopes) As String()
            Return (From scope As KeyValuePair(Of DriveScopes, String) In Me.scopeDict
                    Where Me.Scope.HasFlag(scope.Key)
                    Select scope.Value).ToArray()
        End Function
#End Region

#Region " IDisposable Implementation "
        Private isDisposed As Boolean = False

        Public Sub Dispose() Implements IDisposable.Dispose
            Me.Dispose(isDisposing:=True)
            GC.SuppressFinalize(obj:=Me)
        End Sub

        Private Sub Dispose(isDisposing As Boolean)
            If (Not Me.isDisposed) AndAlso (isDisposing) Then
                If (Me.client IsNot Nothing) Then
                    Me.client.Dispose()
                    Me.client = Nothing
                End If
            End If
            Me.isDisposed = True
        End Sub
#End Region

    End Class

' #End If

End Namespace

#End Region
[/code]