André Alves de Lima

Talking about Software Development and more…

Utilizando a API do Google Drive no C# e VB.NET

Hoje em dia é muito difícil encontrar algum aplicativo que não salve algum tipo de informação na nuvem. Com serviços como Dropbox, Google Drive e OneDrive ficando cada vez mais baratos e acessíveis, a nossa vida acaba sendo muito facilitada caso precisemos subir um arquivo para a nuvem a partir da nossa aplicação.

Para facilitar ainda mais a nossa vida, esses serviços sempre contam com APIs que podem ser acessadas nas mais diversas plataformas de desenvolvimento. O Google Drive, por exemplo, conta com uma API bem extensa, possibilitando a manipulação completa dos seus serviços a partir de aplicações de terceiros.

No artigo de hoje eu vou mostrar para você como fazer todo tipo de interação com o Google Drive no C# e VB.NET. Primeiramente nós veremos como habilitar a API do Google Drive na nossa conta e como gerar o arquivo de credenciais que é necessário para o seu acesso. Em seguida, nós aprenderemos todas as operações que podemos executar com a API: listagem, criação, exclusão e download de arquivos.

A API do Google Drive

O Google Drive conta com uma extensa API que possibilita a manipulação do conteúdo das suas contas em projetos que utilizem qualquer linguagem de programação com suporte a serviços REST. No momento da escrita deste artigo, a API está na sua terceira versão.

Se procurarmos na Internet por exemplos da manipulação do Google Drive com .NET, encontraremos uma boa quantidade de artigos que utilizam a segunda versão da API (como essa excelente série que eu utilizei de inspiração para escrever este artigo). Porém, se quisermos utilizar a versão mais nova da API (que já foi lançada há um bom tempo, no final de 2015), acabamos ficando na mão. Existem diversas diferenças entre a versão 2 e a versão 3 da API, que estão todas documentadas aqui.

A própria página da API conta com alguns exemplos em C# (como, por exemplo, este quickstart). Porém, esses exemplos são muito simples e com pouca explicação do que está sendo feito em cada etapa. Além disso, eles estão todos quebrados em funcionalidades, ou seja, nós não conseguimos encontrar um exemplo que aborde todas as principais interações que podemos fazer com o Google Drive através da nossa aplicação. Neste artigo eu vou juntar todas essas informações em um só lugar e vou explicar para você o que está sendo feito em cada etapa.

Gerando o arquivo com as credenciais

Antes de tentarmos desenvolver qualquer funcionalidade na nossa aplicação utilizando a API do Google Drive, nós precisamos habilitar o suporte à API na nossa conta e temos que gerar também um arquivo com as nossas credenciais. Se você ainda não tiver seguido esses passos com a sua conta, este é o link para o assistente.

O primeiro passo é muito simples. Nós só temos que concordar com os termos do serviço (obviamente, nós não temos outra escolha):

Ao concordarmos com os termos, a API será ativada na nossa conta e nós conseguiremos continuar com o próximo passo, que é a criação do nosso arquivo de credenciais:

Na próxima etapa, escolha a API do Google Drive e a opção “Other UI“, uma vez que nós criaremos uma aplicação console Windows:

Em seguida, nós temos a possibilidade de fazer uma configuração muito interessante para o arquivo de credenciais, que basicamente responde à seguinte pergunta: esse arquivo de credenciais dará acesso a todos os arquivos e pastas do Google Drive ou somente a arquivos e pastas gerados por essa aplicação específica? Escolha a opção que melhor se enquadra no cenário da sua aplicação e prossiga para a próxima etapa. No meu caso, eu escolhi a opção “User data“, que dá acesso a todos os arquivos e pastas da conta:

Edit: o James Maxwel me corrigiu nos comentários quanto à questão dos tipos de credenciais. Segue aqui a explicação dele: “A primeira [opção] “User Data” é necessária quando sua aplicação necessita gerenciar os arquivos do usuário, isto exige o consentimento do mesmo. Já a segunda [opção] “Application Data” é necessária quando sua aplicação gerencia sua própria conta no drive e para isto não necessita do consentimento do usuário tendo em vista que você já possui estes dados”. Obrigado pela correção, James!

Agora chegou a hora de escolher um nome para o Client ID e produto. Além disso, caso a sua conta esteja conectada com outras contas do Google, você terá que selecionar o e-mail da conta que você quer utilizar:

Pronto! Finalmente chegamos na última etapa do assistente, onde conseguimos fazer o download do arquivo com as credenciais. Clique no botão “Download” e salve o arquivo “client_id.json” em um local que seja acessível pela aplicação:

Adicionando a referência da API no projeto

Para a nossa sorte, a própria Google implementou um conjunto de classes “helpers” em .NET que fazem o encapsulamento das chamadas da API de maneira mais amigável. Se essas classes não existissem, nós teríamos que fazer as chamadas manualmente através de requisições HTTP.

Esse conjunto de classes está publicado no NuGet com o nome “Google.Apis.Drive.v3“, ou seja, para adicionar a referência no nosso projeto basta procurarmos por esse termo na janela “NuGet Package Manager” ou podemos executar também o comando “Install-Package Google.Apis.Drive.v3” no “Package Manager Console“:

Para facilitar a nossa vida, os exemplos desse artigo serão construídos em um projeto do tipo “Console Application“. Porém, nada impede que você aplique os mesmos conceitos em outros tipos de projeto, como Windows Forms, WPF ou ASP.NET.

Autenticando e conectando no serviço

A primeira coisa que temos que fazer antes de acessarmos a API do Google Drive é nos autenticarmos utilizando aquele arquivo que geramos nas etapas anteriores. Dito isso, vamos criar um método que retornará uma instância da classe “UserCredential” da API do Google Drive. Esse método fará toda a “mágica” da autenticação sempre que precisarmos nos conectar na API.

Dentro desse método nós precisaremos informar três parâmetros importantes: uma stream apontando para o arquivo com as credenciais (“client_id.json” que geramos anteriormente), o escopo das permissões que serão dadas para execução de comandos na API e o caminho para uma pasta onde será armazenado o token da autenticação. Esse token servirá como um “cache” das nossas credenciais, evitando que tenhamos que digitar o nosso usuário e senha novamente todas as vezes que o aplicativo for executado.

Veja como fica o código desse método:

        // C#
        private static Google.Apis.Auth.OAuth2.UserCredential Autenticar()
        {
            Google.Apis.Auth.OAuth2.UserCredential credenciais;

            using (var stream = new System.IO.FileStream("client_id.json", System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                var diretorioAtual = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
                var diretorioCredenciais = System.IO.Path.Combine(diretorioAtual, "credential");

                credenciais = Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(
                    Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(stream).Secrets,
                    new[] { Google.Apis.Drive.v3.DriveService.Scope.DriveReadonly },
                    "user",
                    System.Threading.CancellationToken.None,
                    new Google.Apis.Util.Store.FileDataStore(diretorioCredenciais, true)).Result;
            }

            return credenciais;
        }
    ' VB.NET
    Private Function Autenticar() As Google.Apis.Auth.OAuth2.UserCredential
        Dim Credenciais As Google.Apis.Auth.OAuth2.UserCredential

        Using Stream = New System.IO.FileStream("client_id.json", System.IO.FileMode.Open, System.IO.FileAccess.Read)
            Dim DiretorioAtual = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location)
            Dim DiretorioCredenciais = System.IO.Path.Combine(DiretorioAtual, "credential")

            Credenciais = Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(
                Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(Stream).Secrets,
                New String() {Google.Apis.Drive.v3.DriveService.Scope.DriveReadonly},
                "user",
                System.Threading.CancellationToken.None,
                New Google.Apis.Util.Store.FileDataStore(DiretorioCredenciais, True)).Result
        End Using

        Return Credenciais
    End Function

À primeira vista esse código parece bem complicado. Porém, ele é mais simples do que parece. Primeiramente nós abrimos um FileStream somente leitura apontando para o arquivo “client_id.json“, que você terá que copiar para o diretório “bin/debug” do projeto. Em seguida, nós criamos uma variável que armazenará o caminho completo para um subdiretório da aplicação, chamado de “credential“. Esse é o diretório onde o token com as credenciais será armazenado. Por fim, nós fazemos a chamada ao método “GoogleWebAuthorizationBroker.AuthorizeAsync“, que deverá receber esses e outros parâmetros.

Note que a princípio estamos pedindo somente a permissão de leitura para a API (DriveReadonly). Ou seja, com essas permissões nós só conseguiremos listar as informações do nosso Google Drive. Mais para a frente nós veremos como essa permissão se comportará ao tentarmos escrever alguma alteração nos objetos da nossa conta.

Os parâmetros “user” e “CancellationToken.None” eu sinceramente não sei para que servem. Eu copiei essa chamada do exemplo oficial da própria Google e não consegui entender a utilidade desses parâmetros. Se alguém souber ou descobrir, avisa nos comentários.

Enfim, uma vez autenticado no serviço, nós temos que iniciar uma conexão. Para isso, nós temos que criar uma nova instância da classe “DriveService” passando um “Initializer” com as nossas credenciais. Entendeu? Pois é, eu sei que é complicado, então vamos ao código:

        // C#
        private static Google.Apis.Drive.v3.DriveService AbrirServico(Google.Apis.Auth.OAuth2.UserCredential credenciais)
        {
            return new Google.Apis.Drive.v3.DriveService(new Google.Apis.Services.BaseClientService.Initializer()
            {
                HttpClientInitializer = credenciais
            });
        }
    ' VB.NET
    Private Function AbrirServico(Credenciais As Google.Apis.Auth.OAuth2.UserCredential) As Google.Apis.Drive.v3.DriveService
        Return New Google.Apis.Drive.v3.DriveService(New Google.Apis.Services.BaseClientService.Initializer() With {
            .HttpClientInitializer = Credenciais
        })
    End Function

Bem mais simples do que quando eu tentei explicar, não é mesmo?

OK. Agora nós já temos o código que faz a autenticação e o código que abre uma conexão com a API do Google Drive. O próximo passo é implementar os métodos que farão a interação com o conteúdo do nosso repositório. Porém, qualquer interação que queiramos fazer com a API, nós precisaremos de uma instância da classe “DriveService” pronta para uso. Dessa forma, no local onde faremos as chamadas à API (por exemplo, o método “main” de um projeto console), nós criaremos um bloco “using” que fará a abertura do serviço:

            // C#
            var credenciais = Autenticar();

            using (var servico = AbrirServico(credenciais))
            {
            }
        ' VB.NET
        Dim Credenciais = Autenticar()

        Using Servico = AbrirServico(Credenciais)

        End Using

Como a classe “DriveService” implementa a interface “IDisposable“, ao colocarmos o código dentro de um bloco “using“, a conexão com a API será devidamente fechada e descartada assim que o bloco “using” for terminado, evitando que nós tenhamos que implementar código extra para fecharmos a conexão. Todo o código que fará a manipulação do nosso Google Drive deverá ser implementado dentro desse bloco “using“.

Listagem de arquivos

Com o serviço inicializado, vamos partir para a interação com os arquivos e pastas do nosso Google Drive. Primeiramente, vamos listar todo o conteúdo do nosso repositório?

Todos os métodos de interação do Google Drive estão implementados na propriedade “Files” da classe “DriveService“. Por exemplo, para criarmos um request que fará a listagem dos arquivos, nós teremos que chamar o método “servico.Files.List“. Essa mesma ideia servirá como base para os outros tipos de operações nas próximas seções deste artigo. Vamos ver como é que fica o código, dessa forma fica mais fácil de explicar:

        // C#
        private static void ListarArquivos(Google.Apis.Drive.v3.DriveService servico)
        {
            var request = servico.Files.List();
            request.Fields = "files(id, name)";
            var resultado = request.Execute();
            var arquivos = resultado.Files;

            if (arquivos != null && arquivos.Any())
            {
                foreach (var arquivo in arquivos)
                {
                    Console.WriteLine(arquivo.Name);
                }
            }
        }
    ' VB.NET
    Private Sub ListarArquivos(Servico As Google.Apis.Drive.v3.DriveService)
        Dim Request = Servico.Files.List()
        Request.Fields = "files(id, name)"
        Dim Resultado = Request.Execute()
        Dim Arquivos = Resultado.Files

        If Arquivos IsNot Nothing AndAlso Arquivos.Any() Then
            For Each Arquivo In Arquivos
                Console.WriteLine(Arquivo.Name)
            Next
        End If
    End Sub

Como você pode ver, primeiro nós criamos um request para o método de listagem de arquivos (“Files.List“). Em seguida, nós especificamos quais são os campos dos arquivos e pastas que devem ser retornados pelo request. Essa é uma grande diferença entre a segunda e a terceira versões da API. Pelo que eu entendi, na segunda versão, todos os campos eram retornados automaticamente. Já na terceira versão, nós precisamos especificar quais campos devem ser retornados, senão a API só retornará o ID dos arquivos e pastas.

Por fim, nós executamos o request e percorremos o resultado (que é uma lista de arquivos e pastas que estão armazenados no nosso Google Drive), imprimindo o nome dos itens. Vamos chamar esse método dentro do nosso bloco “using” para vermos o resultado:

                // C#
                Console.WriteLine("Listagem");
                ListarArquivos(servico);
                Console.WriteLine("Fim Listagem");
                Console.ReadLine();
            ' VB.NET
            Console.WriteLine("Listagem")
            ListarArquivos(Servico)
            Console.WriteLine("Fim Listagem")
            Console.ReadLine()

Aparentemente tudo funcionou perfeitamente, não é mesmo? Porém, essa metodologia só retornará os 100 primeiros itens que forem encontrados no nosso Google Drive. Se quisermos que mais itens sejam retornados, temos que alterar a propriedade “PageSize” do nosso request antes de executá-lo. Por exemplo:

            // C#
            request.PageSize = 1000;
            var resultado = request.Execute();
        ' VB.NET
        Request.PageSize = 1000
        Dim Resultado = Request.Execute()

O valor padrão dessa propriedade é “100“, e o máximo é “1000“. Se tentarmos utilizar um valor maior do que 1000, receberemos o seguinte erro:

Outro detalhe importante é que, por padrão, a listagem de arquivos também retorna todos os arquivos que estiverem na lixeira. Se esse não for o comportamento que você está querendo, basta configurar um filtro para o request, através da propriedade “Q“. Exemplo:

// C#
request.Q = "trashed=false";
' VB.NET
Request.Q = "trashed=false"

Listagem paginada

Como vimos na seção anterior, o máximo de arquivos e pastas que serão listados pela API do Google Drive é 1000. Mas, o que fazemos se quisermos listar mais do que 1000 itens? Nesse caso, a saída é fazer uma listagem paginada, ou seja, retornarmos “X” itens de cada vez.

Para fazermos isso, nós temos que retornar também o “nextPageToken” na hora de listarmos os itens. Com isso, sempre que executarmos o request, caso ainda existam itens para serem retornados, o resultado sempre contará com um token que possibilitará a listagem da próxima página. Veja como é que fica o código de um novo método para listagem de arquivos que receberá também a quantidade de itens por página:

        // C#
        private static void ListarArquivosPaginados(Google.Apis.Drive.v3.DriveService servico, int arquivosPorPagina)
        {
            var request = servico.Files.List();
            request.Fields = "nextPageToken, files(id, name)";
            //request.Q = "trashed=false";
            // Default 100, máximo 1000.
            request.PageSize = arquivosPorPagina;
            var resultado = request.Execute();
            var arquivos = resultado.Files;

            while (arquivos != null && arquivos.Any())
            {
                foreach (var arquivo in arquivos)
                {
                    Console.WriteLine(arquivo.Name);
                }

                if (resultado.NextPageToken != null)
                {
                    Console.WriteLine("Digite ENTER para ir para a próxima página");
                    Console.ReadLine();
                    request.PageToken = resultado.NextPageToken;
                    resultado = request.Execute();
                    arquivos = resultado.Files;
                }
                else
                {
                    arquivos = null;
                }
            }
        }
    ' VB.NET
    Private Sub ListarArquivosPaginados(Servico As Google.Apis.Drive.v3.DriveService, ArquivosPorPagina As Integer)
        Dim Request = Servico.Files.List()
        Request.Fields = "nextPageToken, files(id, name)"
        'Request.Q = "trashed=false"
        ' Default 100, máximo 1000.
        Request.PageSize = ArquivosPorPagina
        Dim Resultado = Request.Execute()
        Dim Arquivos = Resultado.Files

        While Arquivos IsNot Nothing AndAlso Arquivos.Any()
            For Each arquivo In Arquivos
                Console.WriteLine(arquivo.Name)
            Next

            If Resultado.NextPageToken IsNot Nothing Then
                Console.WriteLine("Digite ENTER para ir para a próxima página")
                Console.ReadLine()
                Request.PageToken = Resultado.NextPageToken
                Resultado = Request.Execute()
                Arquivos = Resultado.Files
            Else
                Arquivos = Nothing
            End If
        End While
    End Sub

No bloco “using“, nós podemos chamar esse novo método, passando a quantidade de itens por página. Por exemplo, o código para listarmos os itens de 10 em 10 ficaria assim:

                // C#
                Console.Clear();
                Console.WriteLine("Listagem paginada");
                ListarArquivosPaginados(servico, 10);
                Console.WriteLine("Fim Listagem paginada");
                Console.ReadLine();
            ' VB.NET
            Console.Clear()
            Console.WriteLine("Listagem paginada")
            ListarArquivosPaginados(Servico, 10)
            Console.WriteLine("Fim Listagem paginada")
            Console.ReadLine()

Veja só o resultado:

Criação de diretórios

Agora que já conseguimos listar os itens do nosso Google Drive, vamos conferir como é que podemos fazer para criarmos um novo diretório. Estranhamente, tudo no Google Drive são “itens“. Ou seja, arquivos e diretórios são ambos tratados como “File” (arquivo). A única diferença é que diretórios possuem um “mime type” específico, que fará com que o Google Drive entenda que ele é um diretório, e não um arquivo.

A criação do diretório é bem simples. Basta criarmos uma nova instância da classe “File” e configurarmos um nome e o “mime type” indicando que ele é um diretório. Em seguida, criamos e executamos um request utilizando o método “Files.Create” passando a instância de “File” que instanciamos anteriormente:

        // C#
        private static void CriarDiretorio(Google.Apis.Drive.v3.DriveService servico, string nomeDiretorio)
        {
            var diretorio = new Google.Apis.Drive.v3.Data.File();
            diretorio.Name = nomeDiretorio;
            diretorio.MimeType = "application/vnd.google-apps.folder";
            var request = servico.Files.Create(diretorio);
            request.Execute();
        }
    ' VB.NET
    Private Sub CriarDiretorio(Servico As Google.Apis.Drive.v3.DriveService, NomeDiretorio As String)
        Dim Diretorio = New Google.Apis.Drive.v3.Data.File()
        Diretorio.Name = NomeDiretorio
        Diretorio.MimeType = "application/vnd.google-apps.folder"
        Dim Request = Servico.Files.Create(Diretorio)
        Request.Execute()
    End Sub

Para criarmos um diretório chamado “NovoDiretorio” temos que fazer a seguinte chamada dentro do nosso bloco “using“:

                // C#
                Console.Clear();
                Console.WriteLine("Criar diretório");
                CriarDiretorio(servico, "NovoDiretorio");
                Console.WriteLine("Fim Criar diretório");
                Console.ReadLine();
            ' VB.NET
            Console.Clear()
            Console.WriteLine("Criar diretório")
            CriarDiretorio(Servico, "NovoDiretorio")
            Console.WriteLine("Fim Criar diretório")
            Console.ReadLine()

Porém, ao tentarmos executar esse código com o escopo de permissões que utilizamos anteriormente (“Scope.DriveReadonly“), nós receberemos um erro informando que não temos permissões suficientes:

Obviamente, o escopo “readonly” não permite a criação ou exclusão de itens. Se quisermos alterar itens no nosso Google Drive, teremos que alterar o escopo para “Scope.Drive” na hora de criarmos as credenciais (método “Autenticar“). Só não esqueça de deletar o subdiretório “credential” dentro da pasta “bin/debug“, uma vez que as credenciais com o escopo menor já estarão cacheadas nesse diretório e a autenticação continuará utilizando esse escopo “readonly” caso você não delete essa pasta para forçar uma nova autenticação.

Atenção! Um leitor do meu site (o Daniel Marques) disse que no teste que ele fez desse código no Windows Forms, ao utilizar o escopo “DriveReadonly”, a API não retornou nenhum erro. O upload simplesmente não funcionou, mas não acusou nenhum erro. Caso você esteja passando por uma situação semelhante, não esqueça de verificar se o escopo está corretamente configurado no seu método de autenticação!

Depois de seguir todos esses passos, ao executarmos novamente a aplicação, este será o resultado no nosso Google Drive:

Só tome cuidado, pois outra coisa estranha do Google Drive é que ele não liga para nomes repetidos. Ou seja, se você executar esse código duas vezes, ele criará duas vezes o mesmo diretório sem problema algum:

Deletando arquivos ou diretórios

A próxima operação que vamos conferir neste artigo é a exclusão de itens do nosso Google Drive. A exclusão em si é muito simples. Basta criarmos e executarmos um request para o método “Files.Delete” passando o “id” do item a ser deletado. A parte mais difícil está em descobrir o “id” do item que estamos querendo deletar.

Para descobrirmos o “id” de um item através do seu nome, nós temos que basicamente executar um comando de listagem filtrado, requisitando somente o “id” dos itens que tenham um nome específico. Vamos implementar primeiramente um método que retornará esses “ids“:

        // C#
        private static string[] ProcurarArquivoId(Google.Apis.Drive.v3.DriveService servico, string nome, bool procurarNaLixeira = false)
        {
            var retorno = new List<string>();

            var request = servico.Files.List();
            request.Q = string.Format("name = '{0}'", nome);
            if (!procurarNaLixeira)
            {
                request.Q += " and trashed = false";
            }
            request.Fields = "files(id)";
            var resultado = request.Execute();
            var arquivos = resultado.Files;

            if (arquivos != null && arquivos.Any())
            {
                foreach (var arquivo in arquivos)
                {
                    retorno.Add(arquivo.Id);
                }
            }

            return retorno.ToArray();
        }
    ' VB.NET
    Private Function ProcurarArquivoId(Servico As Google.Apis.Drive.v3.DriveService, Nome As String, Optional ProcurarNaLixeira As Boolean = False) As String()
        Dim Retorno = New List(Of String)()

        Dim Request = Servico.Files.List()
        Request.Q = String.Format("name = '{0}'", Nome)
        If Not ProcurarNaLixeira Then
            Request.Q += " and trashed = false"
        End If
        Request.Fields = "files(id)"
        Dim Resultado = Request.Execute()
        Dim Arquivos = Resultado.Files

        If Arquivos IsNot Nothing AndAlso Arquivos.Any() Then
            For Each Arquivo In Arquivos
                Retorno.Add(Arquivo.Id)
            Next
        End If

        Return Retorno.ToArray()
    End Function

Note que o método já está preparado para procurar itens na lixeira também. No nosso caso, nós não precisaremos dessa opção, mas já é bom implementá-la caso precisemos mais adiante.

Agora que já conseguimos uma lista com os “ids” dos itens, a exclusão fica muito simples:

        // C#
        private static void DeletarItem(Google.Apis.Drive.v3.DriveService servico, string nome)
        {
            var ids = ProcurarArquivoId(servico, nome);
            if (ids != null && ids.Any())
            {
                foreach (var id in ids)
                {
                    var request = servico.Files.Delete(id);
                    request.Execute();
                }
            }
        }
    ' VB.NET
    Private Sub DeletarItem(Servico As Google.Apis.Drive.v3.DriveService, Nome As String)
        Dim Ids = ProcurarArquivoId(Servico, Nome)
        If Ids IsNot Nothing AndAlso Ids.Any() Then
            For Each Id In Ids
                Dim Request = Servico.Files.Delete(Id)
                Request.Execute()
            Next
        End If
    End Sub

Por fim, a chamada para deletarmos o diretório “NovoDiretorio” que criamos anteriormente ficaria da seguinte maneira:

                // C#
                Console.Clear();
                Console.WriteLine("Deletar item");
                DeletarItem(servico, "NovoDiretorio");
                Console.WriteLine("Fim Deletar item");
                Console.ReadLine();
            ' VB.NET
            Console.Clear()
            Console.WriteLine("Deletar item")
            DeletarItem(Servico, "NovoDiretorio")
            Console.WriteLine("Fim Deletar item")
            Console.ReadLine()

Fazendo o upload de arquivos

O upload de arquivos no Google Drive parece ser bem tranquilo à primeira vista. Temos à nossa disposição o método “Files.Create” que recebe uma instância de “File” (com as informações de nome e tipo do arquivo), a Stream com o conteúdo do arquivo e o seu “mime type“.

Se você não sabe o que é “mime type“, ele é um identificador que serve para definir o tipo de um arquivo. Por exemplo, “text/plain” é o “mime type” para arquivos texto, “image/jpeg” é o “mime type” para imagens jpg, e por aí vai. Esse tipo de identificador é muito utilizado em aplicações web na hora de fazer uma requisição.

Para nos ajudar com o cálculo do “mime type” no nosso projeto de exemplo, vamos utilizar a biblioteca MimeTypeMap, que é basicamente um dicionário gigante de “mime types” por extensão de arquivo. Adicione uma referência a essa biblioteca procurando por “MediaTypeMap” no NuGet:

Em seguida, vamos implementar o método que fará o upload do arquivo:

        // C#
        private static void Upload(Google.Apis.Drive.v3.DriveService servico, string caminhoArquivo)
        {
            var arquivo = new Google.Apis.Drive.v3.Data.File();
            arquivo.Name = System.IO.Path.GetFileName(caminhoArquivo);
            arquivo.MimeType = MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(caminhoArquivo));
            using (var stream = new System.IO.FileStream(caminhoArquivo, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                var request = servico.Files.Create(arquivo, stream, arquivo.MimeType);
                request.Upload();
            }
        }
    ' VB.NET
    Private Sub Upload(Servico As Google.Apis.Drive.v3.DriveService, CaminhoArquivo As String)
        Dim Arquivo = New Google.Apis.Drive.v3.Data.File()
        Arquivo.Name = System.IO.Path.GetFileName(CaminhoArquivo)
        Arquivo.MimeType = MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(CaminhoArquivo))
        Using Stream = New System.IO.FileStream(CaminhoArquivo, System.IO.FileMode.Open, System.IO.FileAccess.Read)
            Dim Request = Servico.Files.Create(Arquivo, Stream, Arquivo.MimeType)
            Request.Upload()
        End Using
    End Sub

Pronto! Para fazermos o upload de um arquivo chamado “arquivo.txt” que se encontra na pasta “bin/debug” da nossa aplicação, o código que teríamos que colocar no bloco “using” seria este:

                // C#
                Console.Clear();
                Console.WriteLine("Upload");
                Upload(servico, "arquivo.txt");
                Console.WriteLine("Fim Upload");
                Console.ReadLine();
            ' VB.NET
            Console.Clear()
            Console.WriteLine("Upload")
            Upload(Servico, "arquivo.txt")
            Console.WriteLine("Fim Upload")
            Console.ReadLine()

E este seria o resultado no nosso Google Drive:

Tudo isso funciona muito bem da primeira vez que executarmos esse código. Porém, se executarmos uma segunda vez, ao invés do arquivo ser substituído, um novo “arquivo.txt” será criado no nosso Google Drive. É simplesmente incompreensível o fato do Google Drive trabalhar dessa maneira, possibilitando que existam dois arquivos com o mesmo nome no mesmo diretório. Mas, enfim, é assim que ele funciona.

Para corrigirmos esse problema (ou seja, substituirmos o arquivo caso ele já exista), teremos que detectar se o arquivo já existe e, caso positivo, temos que utilizar o método “Files.Update“, ao invés de “Files.Create“:

        // C#
        private static void Upload(Google.Apis.Drive.v3.DriveService servico, string caminhoArquivo)
        {
            var arquivo = new Google.Apis.Drive.v3.Data.File();
            arquivo.Name = System.IO.Path.GetFileName(caminhoArquivo);
            arquivo.MimeType = MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(caminhoArquivo));

            using (var stream = new System.IO.FileStream(caminhoArquivo, System.IO.FileMode.Open, System.IO.FileAccess.Read))
            {
                var ids = ProcurarArquivoId(servico, arquivo.Name);
                Google.Apis.Upload.ResumableUpload<Google.Apis.Drive.v3.Data.File, Google.Apis.Drive.v3.Data.File> request;

                if (ids == null || !ids.Any())
                {
                    request = servico.Files.Create(arquivo, stream, arquivo.MimeType);
                }
                else
                {
                    request = servico.Files.Update(arquivo, ids.First(), stream, arquivo.MimeType);
                }

                request.Upload();
            }
        }
    ' VB.NET
    Private Sub Upload(Servico As Google.Apis.Drive.v3.DriveService, CaminhoArquivo As String)
        Dim Arquivo = New Google.Apis.Drive.v3.Data.File()
        Arquivo.Name = System.IO.Path.GetFileName(CaminhoArquivo)
        Arquivo.MimeType = MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(CaminhoArquivo))

        Using Stream = New System.IO.FileStream(CaminhoArquivo, System.IO.FileMode.Open, System.IO.FileAccess.Read)
            Dim Ids = ProcurarArquivoId(Servico, Arquivo.Name)
            Dim Request As Google.Apis.Upload.ResumableUpload(Of Google.Apis.Drive.v3.Data.File, Google.Apis.Drive.v3.Data.File)

            If Ids Is Nothing OrElse Not Ids.Any() Then
                Request = Servico.Files.Create(Arquivo, Stream, Arquivo.MimeType)
            Else
                Request = Servico.Files.Update(Arquivo, Ids.First(), Stream, Arquivo.MimeType)
            End If

            Request.Upload()
        End Using
    End Sub

Agora sim. Se executarmos esse código mais de uma vez, ele simplesmente substituirá o “arquivo.txt” já existente no nosso Google Drive, utilizando o conteúdo da nova “Stream“.

Baixando um arquivo do Google Drive

Até agora nós já vimos como listar arquivos no Google Drive e como criar e deletar pastas e arquivos. O que é que está faltando? O download de arquivos! Esse é um dos procedimentos mais tranquilos de serem feitos com a API do Google Drive. Nós só temos que criar um request com o método “Files.Get” passando o “id” do arquivo a ser baixado e, em seguida, chamamos o método “Download” passando a “Stream” onde o arquivo deverá ser salvo. Veja só como é simples:

        // C#
        private static void Download(Google.Apis.Drive.v3.DriveService servico, string nome, string destino)
        {
            var ids = ProcurarArquivoId(servico, nome);
            if (ids != null && ids.Any())
            {
                var request = servico.Files.Get(ids.First());
                using (var stream = new System.IO.FileStream(destino, System.IO.FileMode.Create, System.IO.FileAccess.Write))
                {
                    request.Download(stream);
                }
            }
        }
    ' VB.NET
    Private Sub Download(Servico As Google.Apis.Drive.v3.DriveService, Nome As String, Destino As String)
        Dim Ids = ProcurarArquivoId(Servico, Nome)
        If Ids IsNot Nothing AndAlso Ids.Any() Then
            Dim Request = Servico.Files.[Get](Ids.First())
            Using Stream = New System.IO.FileStream(Destino, System.IO.FileMode.Create, System.IO.FileAccess.Write)
                Request.Download(Stream)
            End Using
        End If
    End Sub

Para baixarmos o “arquivo.txt” que fizemos o upload na seção anterior, a chamada ficaria assim:

                // C#
                Console.Clear();
                Console.WriteLine("Download");
                Download(servico, "arquivo.txt", "arquivoBaixado.txt");
                Console.WriteLine("Fim Download");
                Console.ReadLine();
            ' VB.NET
            Console.Clear()
            Console.WriteLine("Download")
            Download(Servico, "arquivo.txt", "arquivoBaixado.txt")
            Console.WriteLine("Fim Download")
            Console.ReadLine()

Enviando um item para a lixeira

Por fim, a última coisa que quero mostrar para você neste artigo é: como enviamos um item para a lixeira? Na segunda versão da API do Google Drive, nós tínhamos à nossa disposição um método específico para enviar um item para a lixeira. Porém, na terceira versão da API a Google decidiu remover esse método.

Para enviarmos um item para a lixeira, nós temos que recuperar o seu “id“, criar uma instância da classe “File” e marcar a propriedade “Trashed” como verdadeiro. Em seguida, nós criamos um request para o método “Files.Update” enviando essa instância de “File“:

        // C#
        private static void MoverParaLixeira(Google.Apis.Drive.v3.DriveService servico, string nome)
        {
            var ids = ProcurarArquivoId(servico, nome);
            if (ids != null && ids.Any())
            {
                foreach (var id in ids)
                {
                    var arquivo = new Google.Apis.Drive.v3.Data.File();
                    arquivo.Trashed = true;
                    var request = servico.Files.Update(arquivo, id);
                    request.Execute();
                }
            }
        }
    ' VB.NET
    Private Sub MoverParaLixeira(Servico As Google.Apis.Drive.v3.DriveService, Nome As String)
        Dim Ids = ProcurarArquivoId(Servico, Nome)
        If Ids IsNot Nothing AndAlso Ids.Any() Then
            For Each Id In Ids
                Dim Arquivo = New Google.Apis.Drive.v3.Data.File()
                Arquivo.Trashed = True
                Dim Request = Servico.Files.Update(Arquivo, Id)
                Request.Execute()
            Next
        End If
    End Sub

A chamada desse método não tem segredo. Basta passarmos o nome do arquivo ou pasta que deverá ser mandado para a lixeira:

                // C#
                Console.Clear();
                Console.WriteLine("Lixeira");
                MoverParaLixeira(servico, "arquivo.txt");
                Console.WriteLine("Fim Lixeira");
                Console.ReadLine();
            ' VB.NET
            Console.Clear()
            Console.WriteLine("Lixeira")
            MoverParaLixeira(Servico, "arquivo.txt")
            Console.WriteLine("Fim Lixeira")
            Console.ReadLine()

E no ASP.NET MVC?

Se você tentar rodar esse mesmo código no ASP.NET MVC, você ficará a princípio contente porque ele funciona perfeitamente enquanto estamos debugando o projeto com o Visual Studio. Porém, ao publicá-lo em qualquer servidor, na hora de autenticar o acesso, a página de confirmação não será exibida e você receberá um erro “Access Denied“. Como resolvemos isso?

Depois de horas testando a ajustando o projeto, eu finalmente consegui fazer a API do Google Drive autenticar no MVC. Eu segui os passos deste tutorial da própria Google, com algumas pequenas correções.

Primeiramente, nós temos que criar uma outra credencial que também possibilite o acesso ao Google Drive pela web (a credencial que nós criamos anteriormente só vale para aplicativos desktop). Para isso, vá até o seu painel de credenciais e escolha a opção “Create credentials -> OAuth Client ID“:

Em seguida, escolha a opção “Web Application”:

E aí vem uma parte muito importante: as URLs de redirecionamento. Nessa área você deve colocar a URL da página onde você vai acessar o seu Google Drive, precedida de “/AuthCallback“. Por exemplo, no meu projeto eu acesso o Google Drive através da view “GoogleDrive/Index“. Por isso, eu coloquei as seguintes URLs de redirecionamento na minha credencial:

Note que eu adicionei uma URL com o endereço final do meu site (publicado no Azure) e uma URL com o endereço apontando para o localhost + porta. Isso fará com que o projeto funcione tanto em modo de debug local quanto no servidor onde a aplicação será publicada. Além disso, eu adicionei tanto a URL com final “Index” como com final “IndexAsync“. Eu não tenho certeza se realmente precisamos tanto da URL com final “Async” e sem final “Async“, mas em alguns testes que eu fiz, o acesso só funcionou quando eu coloquei as duas URLs como redirecionamento.

O próximo passo é adicionarmos a referência à biblioteca “Google.Apis.Auth.Mvc” pelo NuGet. Essa biblioteca tem alguns helpers que nos ajudarão a fazer a autenticação do Google Drive através do MVC.

Uma vez adicionada essa biblioteca, nós temos que incluir uma nova classe chamada “AppFlowMetadata” no nosso projeto. O código dessa classe deverá ser o seguinte:

    // C#
    public class AppFlowMetadata : Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
    {
        private static readonly Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow flow =
            new Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow(new Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow.Initializer
            {
                ClientSecrets = new Google.Apis.Auth.OAuth2.ClientSecrets
                {
                    ClientId = "SEU_ID",
                    ClientSecret = "SEU_SECRET"
                },
                Scopes = new[] { Google.Apis.Drive.v3.DriveService.Scope.Drive },
                DataStore = new Google.Apis.Util.Store.FileDataStore("Drive.Api.Auth.Store")
            });

        public override string GetUserId(System.Web.Mvc.Controller controller)
        {
            // In this sample we use the session to store the user identifiers.
            // That's not the best practice, because you should have a logic to identify
            // a user. You might want to use "OpenID Connect".
            // You can read more about the protocol in the following link:
            // https://developers.google.com/accounts/docs/OAuth2Login.
            var user = controller.Session["user"];
            if (user == null)
            {
                user = Guid.NewGuid();
                controller.Session["user"] = user;
            }
            return user.ToString();

        }

        public override Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow Flow
        {
            get { return flow; }
        }
    }
' VB.NET
Public Class AppFlowMetadata
    Inherits Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
    Private Shared ReadOnly m_flow As Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow = New Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow(New Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow.Initializer() With {
        .ClientSecrets = New Google.Apis.Auth.OAuth2.ClientSecrets() With {
            .ClientId = "SEU_ID",
            .ClientSecret = "SEU_SECRET"
        },
        .Scopes = New String() {Google.Apis.Drive.v3.DriveService.Scope.Drive},
        .DataStore = New Google.Apis.Util.Store.FileDataStore("Drive.Api.Auth.Store")
    })

    Public Overrides Function GetUserId(controller As System.Web.Mvc.Controller) As String
        ' In this sample we use the session to store the user identifiers.
        ' That's not the best practice, because you should have a logic to identify
        ' a user. You might want to use "OpenID Connect".
        ' You can read more about the protocol in the following link:
        ' https://developers.google.com/accounts/docs/OAuth2Login.
        Dim user = controller.Session("user")
        If user Is Nothing Then
            user = Guid.NewGuid()
            controller.Session("user") = user
        End If
        Return user.ToString()

    End Function

    Public Overrides ReadOnly Property Flow() As Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow
        Get
            Return m_flow
        End Get
    End Property
End Class

Nota: não esqueça de substituir “SEU_ID” e “SEU_SECRET” utilizando as informações disponibilizadas no portal de credenciais do Google. Provavelmente é possível ajustarmos essa implementação de forma que o arquivo de credenciais seja carregado (ao invés de informarmos o ID e segredo direto no código), mas eu não consegui encontrar um tempo para fazer esse ajuste. Se você conseguir ajustar, mande o código nos comentários.

Em seguida, temos que adicionar um novo controller no nosso projeto. O nome desse controller deve ser “AuthCallbackController” e o seu código deve ser o seguinte:

    // C#
    public class AuthCallbackController : Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
    {
        protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata FlowData
        {
            get { return new AppFlowMetadata(); }
        }
    }
    ' VB.NET
    Public Class AuthCallbackController
        Inherits Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
        Protected Overrides ReadOnly Property FlowData() As Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
            Get
                Return New AppFlowMetadata()
            End Get
        End Property
    End Class

Por fim, agora nós podemos adicionar o controller que, de fato, fará o acesso ao nosso Google Drive e listará o seu conteúdo. Dentro desse controller, criamos um método (por exemplo, “Index“) com o seguinte código:

        // C#
        public async System.Threading.Tasks.Task<ActionResult> Index(System.Threading.CancellationToken cancellationToken)
        {
            var result = await new Google.Apis.Auth.OAuth2.Mvc.AuthorizationCodeMvcApp(this, new AppFlowMetadata()).
                AuthorizeAsync(cancellationToken);

            if (result.Credential != null)
            {
                var service = new Google.Apis.Drive.v3.DriveService(new Google.Apis.Services.BaseClientService.Initializer
                {
                    HttpClientInitializer = result.Credential,
                    ApplicationName = "ASP.NET MVC Sample"
                });

                ViewBag.Arquivos = ListarArquivos(service);

                return View();
            }
            else
            {
                return new RedirectResult(result.RedirectUri);
            }
        }
        ' VB.NET
        Public Async Function Index(cancellationToken As System.Threading.CancellationToken) As System.Threading.Tasks.Task(Of ActionResult)
            Dim result = Await New Google.Apis.Auth.OAuth2.Mvc.AuthorizationCodeMvcApp(Me, New AppFlowMetadata()).AuthorizeAsync(cancellationToken)

            If result.Credential IsNot Nothing Then
                Dim service = New Google.Apis.Drive.v3.DriveService(New Google.Apis.Services.BaseClientService.Initializer() With {
            .HttpClientInitializer = result.Credential,
            .ApplicationName = "ASP.NET MVC Sample"})

                ViewBag.Arquivos = ListarArquivos(service)

                Return View()
            Else
                Return New RedirectResult(result.RedirectUri)
            End If
        End Function

E a view ficaria assim:

<!--C#-->
@{
    ViewBag.Title = "Index";
}
<h2>Index</h2>
@foreach (var item in ViewBag.Arquivos)
{
    <div>@item</div>
}
<!--VB.NET-->
@Code
    ViewData("Title") = "Index"
End Code
<h2>Index</h2>
@For Each Item In ViewBag.Arquivos
@<div>@item</div>
Next Item

Pronto! E com isso nós temos o nosso site MVC acessando o Google Drive com sucesso! Agora você pode ajustar esse código implementando os outros métodos que nós conferimos no início deste artigo.

Concluindo

O acesso à API do Google Drive em projetos .NET não é tão complicado de se implementar. Existem alguns detalhes que são chatos, mas, uma vez que entendemos o funcionamento da API, fica fácil de fazer qualquer tipo de manipulação do Google Drive a partir da nossa aplicação.

No artigo de hoje você aprendeu a habilitar a API do Google Drive na sua conta, bem como a geração do arquivo de credenciais que é necessário para o seu acesso. Em seguida, vimos como listar, fazer o upload, download e exclusão de arquivos do Google Drive no C# e VB.NET. Além disso, nós conferimos também como mandar itens para a lixeira. Por fim, nós vimos como ajustar o código de autorização de forma que ele funcione também em projetos ASP.NET MVC.

E você, já precisou fazer alguma integração com o Google Drive nas suas aplicações? Já pensou na possibilidade de armazenar alguns dados da sua aplicação na sua conta do Google Drive? Quem sabe algum backup ou disponibilizar novas versões da aplicação? Conte pra gente nos comentários a sua experiência com o Google Drive ou talvez as ideias que você teve após ter lido este artigo.

Baixe o projeto de exemplo

Para baixar o projeto de exemplo desse artigo, assine a minha newsletter. Ao fazer isso, além de ter acesso ao projeto, você receberá um e-mail toda semana sobre o artigo publicado e ficará sabendo também em primeira mão sobre o artigo da próxima semana, além de receber dicas “bônus” que eu só compartilho por e-mail. Inscreva-se utilizando o formulário no final do artigo.

Até a próxima!

André Lima

Newsletter do André Lima

* indicates required



Powered by MailChimp

156 thoughts on “Utilizando a API do Google Drive no C# e VB.NET

  • Ricardo disse:

    Olá, mesmo assinando a newslatter não encontro o link pra baixar os exemplos :)

  • Marlon Tiedt disse:

    Parabéns pelo post.
    Só uma grande dúvida, você conseguiu implementar o Google Drive Api em MVC?

    Tenho um projeto que somente funciona em ambiente local, e no servidor não funciona nem a pau. Para na linha

    Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync

    Teria alguma dica?

    • andrealveslima disse:

      Olá Marlon, obrigado pelo comentário!

      Sendo sincero com você, eu não testei o código em um projeto MVC.. A única coisa que eu imagino que possa dar errado nesse processo é a hora em que a API abre o browser para você autorizar o acesso do aplicativo ao Google Drive.. Se estiver rodando no IIS, acredito que isso possa dar algum problema..

      Aliás, pesquisando aqui eu acabei de achar que aparentemente esse é realmente o problema.. Você já chegou a dar uma olhada nesta thread do StackOverflow:

      GoogleWebAuthorizationBroker in MVC For Google Drive Access

      ?

      Se eu conseguir um tempo nessa semana eu testo aqui em um projeto MVC para ver se eu consigo fazer funcionar.. Se você conseguir com as informações desse link do StackOverflow, me avisa..

      Abraço!
      André Lima

    • andrealveslima disse:

      Olá Marlon!

      Consegui fazer funcionar no MVC.. Eu adicionei uma seção aqui no artigo mostrando os ajustes que eu tive que fazer no projeto MVC.. Dá uma olhada e me avisa se funcionou no seu projeto..

      Abraço!
      André Lima

  • Wilson de Oliveira disse:

    Sensancional.

  • Petronio Filho disse:

    Olá André!

    Gostaria de fazer o download do código. Já estou na sua newslatter.

    email: camposfilho84@gmail.com

  • Dario Ferreira Franca disse:

    Tem como implementar uma progressbar na parte de dawnload poderia colocar um exemplo?

    • andrealveslima disse:

      Olá Dario, obrigado pelo comentário!

      Nunca implementei isso, mas dei uma pesquisada aqui e encontrei uma informação interessante no StackOverflow.. O Request tem uma propriedade chamada MediaDownloader que, por sua vez, tem um evento chamado ProgressChanged.. Com esse evento, você sempre tem a quantidade de bytes que já foram baixados até o momento.. Dividindo essa informação pela quantidade de bytes total do arquivo que está sendo baixado, você tem o progresso em porcentagem, que você poderia utilizar em uma progress bar no seu projeto..

      Você já tentou fazer dessa maneira?

      Abraço!
      André Lima

  • Ricardo disse:

    102/5000
    Olá, quando eu envio não me dá erro, mas não o arquivo é enviado, eu preciso de sua ajuda, obrigado

    • andrealveslima disse:

      Olá Ricardo, obrigado pelo comentário!

      Como é que está exatamente o seu código? Idêntico ao que eu postei aqui no site ou você fez alguma alteração? Você poderia enviar o seu código e um screenshot (por e-mail, se preferir) para eu conseguir entender melhor o erro que está acontecendo aí no seu projeto?

      Abraço!
      André Lima

  • James Maxwel disse:

    Grande artigo amigo, muito bem elaborado e obrigado por compartilhar seu conhecimento.

    Gostaria de sugerir uma correção quanto aos tipos de credenciais que mencionaste.

    A primeira “User Data” é necessário quando sua aplicação necessita gerenciar os arquivos do usuário, isto exige o consentimento do mesmo;

    Já a segunda “Application Data” é necessário quando sua aplicação gerencia sua própria conta no drive e para isto não necessita do consentimento do usuário tendo em vista que você já possui estes dados.

    Abraço
    James Maxwel

    • andrealveslima disse:

      Olá James, muito obrigado pelo comentário!

      Agradeço também por você ter feito essa correção quanto aos tipos de credenciais.. Já adicionei a correção no texto do artigo.. Valeu! :)

      Abraço!

  • James Maxwel disse:

    André Lima, seria possível retomar o download de onde ele parou? não estou conseguindo alterara requisição(não sei como atribuir o range no header do request)
    estou desenvolvendo em VB.Net

    • andrealveslima disse:

      Olá novamente James!

      Infelizmente eu não faço ideia de como podemos pausar e resumir o download de arquivos com a API do Google Drive.. Coloquei esse ponto aqui na minha lista e, assim que eu conseguir pesquisar, eu te aviso.. Se você conseguir resolver antes, volta aqui e conta pra gente como você resolveu.. Aí eu adiciono essa parte no artigo também..

      Abraço!
      André Lima

  • Jesus disse:

    Saludos, example code?…

  • Arilo Camilo de Souza disse:

    Boa tarde,André, td bem?

    Gostei muito do seu artigo sobre integração com o Google Drive…
    Aqui onde trabalho,estou tentando fazer algo parecido..
    O problema é: Não há na documentação do Google, as DLL e o código para implementar o download, upload , autenticação e listagem de arquivos quando a aplicação é do tipo Webforms. Não dá pra importar essas DLL pq são específicas do MVC.
    Tem alguma dica?

    • andrealveslima disse:

      Olá Arilo, muito obrigado pelo comentário!

      Nunca implementei as funcionalidades do Google Drive em um projeto Web Forms, mas acredito que não deva ser muito diferente do MVC.. Primeiramente, as classes “base” da API do Google Drive funcionam em todas as plataformas, inclusive Console, Windows Forms, WPF, etc.. Essas classes você pode utilizar no Web Forms com certeza (ou seja, o código do upload, download, etc será idêntico ao que eu apresentei aqui neste artigo).. A grande diferença será na autenticação..

      No final do artigo eu mostrei como fazer a autenticação com o MVC, utilizando aquela classe helper do NuGet (Google.Apis.Auth.Mvc).. No próprio NuGet tem outra classe helper para projetos web, sem ser MVC (Google.Apis.Oauth2.v2).. Você já chegou a dar uma olhada nela?

      E tem este artigo aqui que mostra como fazer a implementação no Web Forms (eu não testei):

      Google Drive API v2 for ASP.Net webforms

      Dá uma olhada e depois avisa se ajudou em algo..

      Abraço!
      André Lima

    • Pedro Marcello Queiroz das Chagas disse:

      Eu usei o modelo do André como base, e fiz uma dll separada, exclusiva para isso, dai é realizar algumas alterações nos métodos internos, sinceramente não precisava de todos só os de delete, upload e download. Optei por externalizar para conseguir usar o modelo postado como base.

      • andrealveslima disse:

        Olá Pedro!

        Muito obrigado por ter deixado esse feedback aqui no comentário do Arilo.. Fico feliz que o conteúdo do artigo tenha te ajudado a construir essa dll que você está utilizando no seu projeto..

        Abraço!
        André Lima

  • joao batista disse:

    Apesar de ter feito todo cadastro não acho como acessar a sua newsletter.
    Por favor pode informar ou mandar um link de acesso

    • andrealveslima disse:

      Olá João!

      Acredito que você estava querendo acessar os projetos de exemplo, correto? Se for isso, eu mandei o link no seu e-mail.. Se for outra coisa, é só avisar..

      Abraço!
      André Lima

  • Thiago Monteiro disse:

    Boa tarde,André, td bem?

    Muito bom esse artigo, estou com uma dúvida que não consegui encontrar na internet, pode me ajudar?
    Seria em como enviar um arquivo para uma determinada pasta, procurei em vários lugares e não encontrei. Obrigado

    • andrealveslima disse:

      Olá Thiago, muito obrigado pelo comentário!

      Para adicionar um arquivo em uma pasta específica, você precisa primeiro pegar o ID da pasta e depois setar na propriedade “Parents” do arquivo:

                  arquivo.MimeType = MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(caminhoArquivo));           
                  var idPasta = ProcurarArquivoId(servico, "NovoDiretorio").First();
                  arquivo.Parents = new List<string>(new string[] { idPasta });
      

      Depois, na hora de criar o request, você precisa adicionar na lista de fields a coluna “parents”:

                      if (ids == null || !ids.Any())
                      {
                          var theRequest = servico.Files.Create(arquivo, stream, arquivo.MimeType);
                          theRequest.Fields = "id, parents";
                          request = theRequest;
                      }
      

      Testa aí e depois me fala se funcionou..

      Abraço!
      André Lima

  • Olá André, boa noite.
    Estou com problemas no meu atualizador de arquivos, pois ele fica a todo momento solicitando credenciais de acesso.
    Eu gostaria de saber se você teria ai um exemplo usando a autenticação do tipo “Credenciais padrão do aplicativo”, no seu exemplo você usa UserCredential
    Muito obrigado

    • andrealveslima disse:

      Olá Renan!

      Que estranho hein.. Qual é o tipo de projeto? Console, desktop, web? No exemplo que eu mostrei no artigo, ele só pede as credenciais uma vez, aí fica armazenado o token em disco para as próximas execuções da aplicação.. Você chegou a testar exatamente esse código que eu mostrei no artigo?

      Abraço!
      André Lima

  • Braga disse:

    Prezado Andre, boa tarde!

    Gostei muito do seu artigo:
    http://www.andrealveslima.com.br/blog/index.php/2017/04/12/utilizando-api-google-drive-no-c-e-vb-net/

    Assinei a newletter, confirmei o email, porém quando aparece para baixar o código, me vem um link diverso, veja:


    Inscrição confirmada
    Sua assinatura de nossa lista foi confirmada.

    Clique nos links abaixo para fazer o download dos seus brindes:

    Lista de Recursos do Report Viewer
    Resumo em tópicos: 80/20 Sales and Marketing

    Agradecemos a inscrição!

    Esses dois links não tem relação com o artigo, estou informando para te pedir o código, mas também para que você fiquei ciente, para poder arrumar o problema.

    Poderia me enviar o código no email?

    Att

    • andrealveslima disse:

      Olá Braga!

      Respondi o seu e-mail com a mesma dúvida.. Se quiser, podemos continuar a discussão por lá ou por aqui mesmo..

      Abraço!
      André Lima

  • Everson Jean disse:

    Olá, queria saber como upar um arquivo em determinada pasta do GDrive, já andei procurando o código pra isto mas não encontrei :(

  • Marcos H. Horst Cavalli disse:

    Cara, estou recebendo o erro “At least one client secrets (Installed or Web) should be set” ao tentar autenticar(ocorre no seguinte trecho:
    cred = Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsync(
    Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(stream).Secrets,
    new[] { Google.Apis.Drive.v3.DriveService.Scope.Drive },
    “user”, System.Threading.CancellationToken.None,
    new Google.Apis.Util.Store.FileDataStore(diretorioCredenciais, true)).Result;)
    Está a copia do seu, porém não faço a menor ideia de como consertar, poderia me ajudar com isto?

    • Marcos H. Horst Cavalli disse:

      Acabei conseguindo corrigir esta versão, porém agora ele está abrindo uma guia no google chrome totalmente cinza com a carinha infeliz como icone da página….sabe o que poderia ser?

      • andrealveslima disse:

        Olá Marcos!

        Não tenho a mínima ideia.. Você está tentando executar isso na sua casa ou na empresa / faculdade? Será que você não está atrás de um proxy ao acessar a internet? Você tentou baixar o projeto de exemplo para testar com ele?

        Abraço!
        André Lima

        • Marcos H. Horst Cavalli disse:

          Consegui resolver, era uma simples questão de permissão para o google chrome gerar a credencial no computador(primeiro acesso), a partir do momento em que eu executei o programa em um computador com permissão de adm funcionou normalmente…
          Valeu o retorno=D

  • Edvaldo disse:

    Poderia me enviar o link do exemplo

    • andrealveslima disse:

      Olá Edvaldo!

      Enviei o link no e-mail de boas vindas.. Qualquer coisa, se não conseguir baixar ou se ficar com alguma dúvida, é só entrar em contato..

      Abraço!
      André Lima

  • Rafael Silveira disse:

    André, Bom dia

    Queria fazer um upload de uma imagem vinda de um picturebox, como faço sem precisar criar um arquivo antes? ou seja, pegando a imagem do picturebox e salvando diretamente no google drive?
    Obrigado! Excelente material

    • andrealveslima disse:

      Olá Rafael, obrigado pelo comentário!

      Nesse caso você só precisa salvar o conteúdo do PictureBox em um MemoryStream e depois você pode continuar utilizando o método servico.Files.Create que demonstrei no artigo, uma vez que o segundo parâmetro desse método já é uma Stream..

      Para salvar o conteúdo do PictureBox em MemoryStream, dê uma olhada nesta thread do StackOverflow:

      Save image from picturebox in stream format

      Abraço!
      André Lima

  • Leandro Alves disse:

    Eu só queria dizer muito obrigado por compartilhar. Seu artigo tem informações valiosíssimas. Vou tentar aplicar suas instruções na api do YouTube também. Acredito que não deva ser muito diferente. Abaço!

    • andrealveslima disse:

      De nada, Leandro! Acredito que principalmente a parte de autenticação vai ser bem parecida.. O resto, obviamente vai mudar um pouco, uma vez que os comandos que você consegue fazer com o Youtube são bem diferentes do que você consegue fazer com o Google Drive.. Tenta aí e depois volta aqui contar pra gente os resultados.. :)

      Abraço!
      André Lima

  • André, tudo bem!?

    Seguinte, estou pensando em utilizar esse tipo de recurso para criar uma pequena aplicação para fazer backup dos bancos de dados SQL Server de meus clientes em VB.Net.

    Porém ainda me paira uma dúvida e preocupação?!

    Como confirmo se o arquivo foi 100% copiado, para garantir que a cópia foi bem sucedida, existe teste para isso? Como seria?!

    Agradeço a atenção!

    • andrealveslima disse:

      Olá José!

      Se você fizer o upload do arquivo de forma síncrona (que é o jeito que eu mostrei no artigo), uma vez que o método Upload tenha sido completamente executado, você pode ter certeza que o upload foi realizado com sucesso.. Ou você receberá uma exception durante a sua execução, o que indica que o upload não foi concluído corretamente..

      Caso você realmente queira confirmar duas vezes, você pode baixar o arquivo novamente e comparar o hash deles para ver se eles batem.. Se bater, significa que o arquivo no Google Drive tem exatamente o mesmo conteúdo do arquivo local.. Se você não souber como fazer a comparação de hashes de arquivos, dá uma olhada neste artigo que eu escrevi uns tempos atrás sobre esse tema:

      Calculando o hash de arquivos para verificação de integridade com C# e VB.NET

      Abraço!
      André Lima

  • fernandofariabrito@gmail.com disse:

    Me envie tbm fernandofariabrito@gmail.com
    vb.net

    • andrealveslima disse:

      Olá Fernando!

      O link para baixar os projetos de exemplo está no e-mail de confirmação da assinatura, que você já deve ter recebido.. Mas, de qualquer forma, acabei de enviar para você um e-mail de boas vindas contendo o link novamente..

      Abraço!
      André Lima

  • Gabriel disse:

    Olá Andre.

    Estou utilizando os seus exemplos, mas estou com dificuldades no upload. Ele executa sem erros quando debugo, porém o arquivo não aparece no meu google drive. Faz ideia do que seja?

    Consigo listar os arquivos do drive pelo código, mas upload não funciona.

    Obrigado, abraços

    Gabriel

    • andrealveslima disse:

      Olá Gabriel!

      Infelizmente não faço ideia.. Você está utilizando o código exatamente como foi indicado no artigo ou você alterou alguma coisa? Tente baixar o projeto de exemplo finalizado para ver se funciona alterando somente o arquivo de credenciais para o seu..

      Abraço!
      André Lima

  • fernandofariabrito@gmail.com disse:

    Duas duvidas que eu fiquei como mudar o diretorio onde é feito o upload. e tbm como acompanhar o processo de upload.
    porque os arquivos estão subindo para raiz do google drive, como alterar este destino, e em qual parte do codigo seria possivel inserir um progressbar ?

  • geovane silva disse:

    Bom dia, segui todos os passos e apos dar um rebuild apresentou um erro: error CS0103 The name ‘MimeTypes’ does not exist in the current context GUI C:\Users\fg\Documents\Visual Studio 2015\Projects\ControleDeMaterial\GUI\Program.cs 251 Active
    Poderia me ajudar???

    • andrealveslima disse:

      Olá Geovane!

      Você adicionou a referência para a biblioteca MimeTypeMap como eu expliquei no artigo? Nesta parte especificamente:

      Abraço!
      André Lima

  • Raissa Carvalho disse:

    Boa tarde, Muito bom o seu post. Consegui implementar na minha aplicação. Mas estou com um problema. Tenho diretórios com nomes diferentes por exemplo A e B , se eu adiciono o arquivo x no diretório A, não consigo incluir ele no diretório B. Porque ele busca o ID do arquivo em todos os diretórios como ele acha no diretório A ele apenas altera no diretório A. Tem como fazer a busca do ID passando o diretório também?
    Obrigada

    • andrealveslima disse:

      Olá Raissa, obrigado pelo comentário!

      Eu não testei, mas teoricamente acredito que se você passar a informação de “parents” com o ID da pasta na hora de buscar o arquivo, você conseguirá procurar pelo arquivo somente em uma pasta específica.. Primeiro você teria que encontrar o ID da pasta (vamos supor que você armazene essa informação em uma variável chamada “idParent”), aí você poderia tentar alterar a busca no método “ProcurarArquivoID” para que ele considere o ID do parent também.. Seria algo como:

      request.Q = string.Format("name = '{0}'", nome);
      if (!procurarNaLixeira)
      {
      	request.Q += " and trashed = false";
      }
      if (!string.IsNullOrEmpty(idParent))
      {
      	request.Q += " and '" + idParent + "' in parents";
      }
      

      Não sei se vai funcionar, mas vale a pena a tentativa..

      Abraço!
      André Lima

  • Gilberto Cunha disse:

    gostaria de receber o codigo deste projeto em c# , vc poderia me encaminhar

    obrigado.

  • Amorim disse:

    Boa tarde voce poderia me enviar esse codigo já assinei seu newsletter porem nao sei como fazer o download.
    Fico no aguardo.

    • andrealveslima disse:

      Olá Josemar!

      Era para você ter recebido o link para a página de downloads no e-mail de confirmação da inscrição.. De qualquer forma, acabei de enviar novamente o link no seu e-mail.. Qualquer coisa é só entrar em contato novamente..

      Abraço!
      André Lima

  • Jonathan disse:

    Olá poderia me enviar pro email, eu não consegui fazer o upload do arquivo eu queria uns exemplos…

  • Diego Silva disse:

    Olá amigo, estou pensando em utilizar o GoogleDrive para fazer backup do meu sistema.
    Tenho varios clientes e a ideia era criar uma pasta para cada e salvar os arquivos dentro das pastas. Seria viável ou tem outra solução mais pratica sem utilizar sistemas de terceiros?
    Outra duvida é em questão ao arquivo client_id.json, seria interessante “criptografar” ele para que os clientes não tenha acesso?

    • andrealveslima disse:

      Olá Diego!

      Acho difícil você conseguir fazer esse tipo de backup com o Google Drive, uma vez que ele obrigatoriamente precisará que o usuário faça um “login” no Google Drive a primeira vez que a aplicação for executada.. Não sei o que acontece com essa janela de login se você mandar também com a aplicação a pasta de “cache” onde ficam os arquivos de credencial depois do primeiro login.. Teria que fazer um teste para ver se a janela não é exibida..

      Quanto ao arquivo client_id.json, acredito que você não precise criptografa-lo.. Ele só contém as informações da conta onde os arquivos serão salvos.. O token de autorização só é gerado quando o usuário fizer o login pela aplicação.. Esses arquivos de cache (que ficam armazenados no subdiretório “credential”) contém o token de acesso para a conta.. Se você optar por distribuir esses arquivos com a sua aplicação, aí eu acho que seria melhor criptografa-los de alguma maneira..

      Abraço!
      André Lima

      • Diego Silva disse:

        Olá André, eu fiz uns testes, não sei se por tempo ele precise logar novamente, mas depois que gera o arquivo de credencial, ele não solicita mais o login. fiz o teste até em outro computador copiando somente o arquivo e não solicitou.
        Vou fazer mais alguns testes e caso funcione sem precisar de login, deixo o feedback aqui. Obrigado por enquanto e sucesso!

        • andrealveslima disse:

          Bacana, Diego.. Que legal que funcionou copiando o arquivo de credencial.. Achei que não fosse funcionar..

          Enfim, quando você tiver tudo rodando direitinho, volta aqui e avisa a gente então.. :)

          Abraço!
          André Lima

          • carlos disse:

            Bom dia,
            Vi sobre o assunto, mas nao entendi, é possível fazer upload em um diretório especifico?
            Exemplo, gero um arquivo e gravo em um diretório, gero outro arquivo e gravo em outro diretorio

          • andrealveslima disse:

            Olá Carlos!

            É possível fazer o upload em um diretório específico sim.. Só que eu não mostrei isso no artigo.. Porém, outras pessoas já fizeram essa pergunta aqui nos comentários e eu respondi.. Clique aqui e veja a minha resposta (ou procure por “determinada pasta” aqui no artigo que você vai encontrar o comentário que eu mencionei)..

            Abraço!
            André Lima

  • geovane disse:

    Boa tarde, acho que não sei onde implementar os códigos, por isso apresentou vários erros na implementação. Na verdade eu preciso passar os dados de uma tabela do SQL Server para uma planilha do google drive, e que essa planilha seja atualizada automaticamente toda vez que os dados da tabela sejam alterados. A titulo de esclarecimento, trata-se de uma tabela de estoque que e alterada durante a movimentação(entrada e saida de material). Será que vc pode me ajudar? Obrigado.

    • andrealveslima disse:

      Olá Geovane!

      Serão vários usuários alterando o mesmo arquivo ao mesmo tempo? Ou somente um usuário de cada vez? Pergunto isso porque, caso múltiplos usuários alterem a planilha ao mesmo tempo, você muito provavelmente terá problemas de conflitos na alteração do arquivo.. Aí acredito que a melhor API do Google que você poderia utilizar nesse caso seria a do Google Docs, e não do Google Drive.. Eu não tenho nenhuma experiência com ela, mas o link da documentação oficial é este:

      .NET Quickstart Google Sheets API

      E quanto aos erros que você está tendo na implementação do código deste artigo, por favor, poste as mensagens de erro detalhadas para conseguirmos te ajudar..

      Abraço!
      André Lima

  • Gabriel disse:

    Olá André!

    Estou tendo um problema ao fazer o upload. Eu preciso fazer o upload para dentro de uma pasta específica, mas nem para o diretório principal está funcionando. Consigo ver os arquivos que tem no meu drive, mas o upload não vai. Por conseguir ver os arquivos listados e não conseguir fazer o upload, parece faltar algum tipo de permissão. Sabe o que poderia ser? Aqui vai um print da parte do código que faz o upload. (TesteUpload é o nome da pasta)

    https://image.prntscr.com/image/YiR8qd8xTamVupgebeXIOg.png

    • Gabriel disse:

      Opa, pra manter atualizado aqui, consegui resolver!

      Era a parte de autenticação, coloquei pra DriveService.Scope.Drive e funcionou.

      Agradeço pelo ótimo tutorial! :D

      • andrealveslima disse:

        Olá Gabriel! Que bom que você conseguiu resolver alterando o escopo das permissões.. Esse detalhezinho acaba pegando muita gente mesmo.. :)

        Qualquer outra dúvida é só entrar em contato novamente..

        Abraço!
        André Lima

  • Osvaldo disse:

    Olá André:

    Excelente publicação!
    Consegui fazer funcionar os seus exemplos. Porém, não consegui uma maneira de listar os arquivos de uma pasta específica. Sei que tem relação com o idParent. Incluui a seguinte linha em Listar Arquivos: Request.Q += ” and ‘” + idParent + “‘ in parents”; mas eu não sei de onde eu pego o idParent. idParent é o nome da pasta ou aquele endereço de link quando compartilhamos uma pasta?

    Desculpe-me pela pergunta básica. Mas é que eu não encontrei nada na internet que pudesse me ajudar.

    Desde já agradeço-lhe pela ajuda e mais uma vez, parabéns pela publicação!

    • Osvaldo disse:

      André:

      Consegui! É o endereço do compartilhamento! Eu não via o resultado porque o console não é aberto enquanto o form estiver aberto.

      Obrigado!

      • andrealveslima disse:

        Olá Osvaldo, muito obrigado pelos comentários!

        Fico feliz por você ter gostado do artigo e por você ter conseguido resolver o seu problema, antes mesmo de eu ter tempo para te responder.. :)

        Qualquer outra dúvida, entre em contato novamente..

        Abraço!
        André Lima

  • Ualace de Oliveira dos Reis disse:

    Boa Tarde, primeiramente parabéns André! Graças a sua impecável explicação, consegui fazer as adaptações do código necessárias ao meu projeto de forma muito tranquila.
    Tenho uma duvida que não está diretamente ligada ao tutorial apresentado, talvez você ou algum outro leitor possa me ajudar.
    Preciso que ao ser realizado o upload de um determinado arquivo, o aplicativo solicite à API que crie um link de compartilhamento do mesmo e retorne-o ao app.
    acredito que na função “private static void Upload(…” eu deva atribuir alguma propriedade ao arquivo: ex arquivo.[não sei qual…], e depois nas funções ProcurarArquivoId ou ListarArquivos, pedir o retorno da propriedade do(s) arquivo(s) que contenha o link de compartilhamento do referido arquivo.
    Desde jà agradeço,
    Ualace

    • andrealveslima disse:

      Olá Ualace, muito obrigado pelo comentário!

      Não sei se você já resolveu esse problema, mas pelo que eu pesquisei aqui, com a API v3 (que é a que estamos utilizando neste artigo), para pegar o link (público) de compartilhamento, você só precisa fazer um request dos arquivos pegando também a coluna “webViewLink”.. Veja se esta thread do StackOverflow te ajuda:

      Using Google Drive V3 API and service account auth, WebViewLink is null

      Abraço!
      André Lima

      • Ualace de Oliveira dos Reis disse:

        Obrigado pela dica, eu consegui resolver de uma outra forma em dois passos:
        1) Fiz o upload dos arquivos para uma pasta previamente marcada como compartilhada, desta forma os arquivos herdam este atributo.
        2) Fiz uma simples Concatenação:
        string Link = “https://drive.google.com/file/d/” + idFile + “/view?usp=sharing”

        • andrealveslima disse:

          Olá Ualace!

          Maravilha hein.. Que bom que deu certo desse jeito.. Obrigado pela dica.. ;)

          Abraço!
          André Lima

        • Huy disse:

          Can you help me get the id of a file “arquivo.txt”.
          I also want to do it like you but I do not know how to get the id of the uploaded file
          For example: Upload (servico, “arquivo.txt”) ==> I want to get its id immediately after upload.
          Thank you.

          • andrealveslima disse:

            Hello!

            You can follow the example from this link and get the ID of the file after calling the “request.Upload” method like this:

            // Just do this after the "request.Upload();" call:
            var file = request.ResponseBody;
            var id = file.Id;
            

            Regards,
            André Lima

  • Diego disse:

    Olá André, muito bom o tutorial

    Gostaria de uma ajuda, ao tentar criar um diretório estou recebendo o seguinte erro:

    https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=ACCESS_TOKEN

    Obrigado

    • Diego disse:

      Insufficient Permission [403]
      Errors [
      Message[Insufficient Permission] Location[ – ] Reason[insufficientPermissions] Domain[global]
      ]

      • andrealveslima disse:

        Olá Diego, obrigado pelo comentário!

        Qual é o escopo que você está utilizando ao criar a variável de credenciais? Se você utilizar o escopo “DriveReadonly”, você não conseguirá criar diretórios.. Você precisa utilizar o escopo “Drive”.. No próprio artigo eu falo exatamente sobre esse erro na parte de criação de diretórios..

        Abraço!
        André Lima

  • Diego Silva disse:

    Bom dia!
    Pesquisei sobre timeout e não encontrei, estou tendo problemas para fazer o upload em conexões mais lentas, já teve algum problema parecido?
    precisava aumentar o tempo de timeout.

    • andrealveslima disse:

      Olá Diego!

      Já tentou setar o Timeout do HttpClient do serviço? Exemplo:

      // Timeout de 1 minuto:
      servico.HttpClient.Timeout = new TimeSpan(0, 1, 0);
      

      Abraço!
      André Lima

  • Diego Silva disse:

    Eu vi esse exemplo, mas não achei onde colocar ele, digo em qual parte do upload.

    • andrealveslima disse:

      Olá Diego!

      Você coloca esse código depois de ter criado a instância de DriveService.. Você chegou a implementar o exemplo apresentado aqui no artigo? No exemplo do artigo, você teria que colocar essa alteração do Timeout logo no início do bloco “using”:

      using (var servico = AbrirServico(credenciais))
      {
      	servico.HttpClient.Timeout = new TimeSpan(0, 1, 0);
      	
      	// Resto do código...
      }
      

      Abraço!
      André Lima

  • Diego Silva disse:

    Bom dia amigo!
    Bem, utilizei um pouco diferente mas deu certo!
    segue abaixo o código!

    using (var stream = new FileStream(caminhoArquivo, FileMode.Open, FileAccess.Read))
    { Google.Apis.Upload.ResumableUpload request;
    var theRequest = Credencial.Files.Create(arquivo, stream, arquivo.MimeType);
    theRequest.Fields = “id, parents”;
    request = theRequest;
    }
    stream.WriteTimeout = 15 * (60 * 1000); // 15 minutos
    request.Upload();
    return;
    }
    }

  • Paulo Henrique da Silva disse:

    Boa tarde Andre. Por favor, poderia me enviar o link do projeto exemplo? Me inscrevi mas não recebi confirmação.

  • Bruno Garra disse:

    trabalho perfeito. google nada disponibiliza dessa forma
    no entanto eu tenho um problema
    existe alguma forma de antes de fazer upload de um ficheiro verificar se fui o ultimo a baixar a versão actual do ficheiro??
    criei um aplicativo que baixa no inicio um ficheiro de base de dados do google e quando encerra envia de novo para o google drive. no entanto muita gente utiliza o aplicativo. de forma que eu nao tenho maneira de validar se eu fui o ultimo a alterar e se posso enviar o ficheiro para o google sem sobrepor o trabalho de outros utilizadores.

    isto é eu queria validar que só envia se fui o ultimo a baixar. se a versão do ficheiro ainda é a mesma. caso contrario baixa a ultima versão primeiro para sincronizar os dados localmente na base de dados e ai sim envia depois o ficheiro para o google drive

    espero ter sido explicito no meu pedido
    muito obrigado

    • andrealveslima disse:

      Olá Bruno, obrigado pelo comentário! Fico feliz por ter conseguido ajudar até aqui..

      Quanto à sua questão, eu nunca precisei fazer isso, mas pesquisei aqui e encontrei duas possíveis soluções..

      1) Você poderia ver o ID da última pessoa que modificou o arquivo. Caso não seja o mesmo de quando você originalmente baixou o arquivo, fica claro que alguma outra pessoa alterou o arquivo nesse meio tempo (mais detalhes neste link)

      2) Você pode utilizar a lista de alterações a partir de um certo ponto no tempo. Se o arquivo estiver dentro dessa lista de alterações, é porque ele foi alterado por alguma outra pessoa (mais detalhes neste link)

      Eu não testei essas opções, mas acho que uma das duas daria certo no seu cenário.. Testa aí e depois conta aqui pra gente se funcionou..

      Abraço!
      André Lima

      • Bruno Garra disse:

        Olá André. Obrigado pela resposta. Irei testar e colocarei em caso de sucesso o meu código para que outros possam fazer o mesmo tipo de implementação nos seus aplicativos. Um abraço.

  • PAULO HENRIQUE DA SILVA disse:

    Boa noite André,veja se consegue me ajudar por favor, adiciono uma pasta no googledrive e consigo pegar o ID e Weblink, porém, a pasta que adiciono não é pública, logo com o link a pessoa precisa solicitar alteração. Se eu entrar manualmente na pasta e “ativar compartilhamento de link” dá certo, mas no meu caso preciso que na própria adição a pasta nova entre assim, ou uma forma de eu alterar. Estou desde cedo tentando descobrir isso. Obrigado.

    • andrealveslima disse:

      Olá Paulo!

      Você conseguiu resolver esse problema? Sinceramente, não sei como fazer para resolve-lo.. Dei uma pesquisada aqui e encontrei uma maneira de fazer em javascript, adicionando uma permissão para o link da pasta para “anyone”:

      Make folder shared google drive api v3?

      Se dá para fazer via javascript, então dá para fazer pela API do .NET também.. A documentação correspondente a essa funcionalidade encontra-se neste link:

      Manage Sharing

      Talvez te ajude em algo.. Depois volta aqui e avisa se deu certo..

      Abraço!
      André Lima

      • Paulo Henrique da Silva disse:

        Olá André!

        Não consegui! Mas, muito obrigado pela ajuda.
        Tentei com os links que você enviou mas não deu.
        Mas por enquanto estamos compartilhando manual mesmo no googledrive. Tendo feito uma vez já fica certo. Sou novo em programação.

        Obrigado,
        Att.

        • andrealveslima disse:

          Olá Paulo!

          Que pena que não deu certo.. Mas, se algum dia você resolver trabalhar nessa funcionalidade de novo, me manda exatamente os erros que você obteve (se é que você obteve algum erro), aí pode ser que eu consiga te ajudar de outra maneira..

          Do mais, sucesso aí no projeto!

          Abraço!
          André Lima

  • Ramon Shuan disse:

    Olá André bom dia!
    Estou precisando muito de uma ajuda sua, quando tento fazer um request via postman o sql Server esta retornando erro 50, já alterei no servidor para aceitar tcp / IP mais não obtive sucesso, poderia me ajudar.

    A API que criei foi diretamente no visual Studio .

    • andrealveslima disse:

      Olá Ramon!

      Pera aí, deixa eu entender.. Você criou uma Web API que conecta com um banco SQL Server e você quer acessar os métodos dessa API pelo Postman? É isso? Ou seria alguma outra coisa? Você poderia explicar detalhadamente o que você fez para chegar nesse cenário?

      Abraço!
      André Lima

  • Bruno Saldanha disse:

    Olá Andre,

    Saberia me dizer por quanto tempo o token fica válido?

    Desde já obrigado!

    • andrealveslima disse:

      Olá Bruno!

      Até onde eu sei, a API do Google Drive trabalha com “refresh tokens” que não expiram.. Ou seja, eles são válidos até que o usuário revogue acesso à sua aplicação na conta dele.. Ou você pode chamar um “RevokeTokenAsync” nas credenciais, aí o acesso será revogado via aplicação..

      Abraço!
      André Lima

  • Alberto Douglas disse:

    Olá André!
    Estou testando seu exemplo. Não estou conseguindo fazer upload para o google drive. Não dá erro nenhum, mas tb não copia o arquivo para lá.
    Vc saberia dizer o que pode estar acontecendo?

    • andrealveslima disse:

      Olá Alberto!

      Estranho hein.. Pra mim funciona normalmente.. Você seguiu exatamente os passos indicados na hora de criar as permissões na API do Google Drive? Testou exatamente com o projeto de exemplo que eu disponibilizo para os assinantes da newsletter?

      Abraço!
      André Lima

  • Alberto Douglas disse:

    Olá André.
    Você não tem algum exemplo usando webforms (.aspx)?

    • andrealveslima disse:

      Olá Alberto! Infelizmente Web Forms não, só com MVC mesmo.. Se você encontrar algum exemplo em Web Forms, volta aqui e posta o link para outras pessoas que possam vir a se interessar..

      Abraço!
      André Lima

  • Rafael Camara disse:

    Olá André,

    Gostaria de tirar uma dúvida com você mas em primeiro lugar parabéns por compartilhar o conhecimento, excelente aplicação.

    Fiz um programa de backup e eu utilizo vb.net. Adaptei o seu código para o mesmo. A autenticação estou fazendo direta no código e não estou utilizando o arquivo client_id.json. Ao iniciar o programa pela primeira vez eu abro o Google Chrome e coloco as credenciais para permitir o acesso da aplicação ao Google drive e após a permissão eu fecho. Percebi algumas vezes que a autenticação esta ficando salva na página do Google, e-mail, Google drive e etc. Minha preocupação é que na estação do usuário que eu colocar essa aplicação ele pode acabar tem acesso ao Google drive deixando os arquivos vulneráveis.

    Não consegui observar no seu código se esta fazendo alguma desconexão ou finalizando o serviço após o upload.

    Você me sugere algo para que eu possa garantir que não existirá mais nenhuma forma de acesso ao Google drive após o upload?

    Muito obrigado mais uma vez pela sua atenção e grato pelo suporte.

    Um abraço
    Rafael
    rafael.camaraa@gmail.com

    • andrealveslima disse:

      Olá Rafael!

      Não sei te dizer ao certo, mas a página que o Google Drive exibe não é um login em si, mas sim somente uma autorização para que o token possa ser gerado e retornado para a aplicação.. Acredito que a conta não fique logada no browser.. Pelo menos não deveria.. Você já tentou fazer um teste abrindo o Google Drive no browser depois da autenticação para ver se dá acesso?

      Abraço!
      André Lima

  • Werinson disse:

    Bom dia! Parabéns pelo show de aula! Como fazer para o arquivo de download ser baixado na pasta Downloads e não na pasta raiz do programa?

  • Werinson disse:

    Conseguimos obter o espaço disponivel para apresentar no projeto? E assim permitir que o usuario saiba se ainda tem espaço para armazenamento…

  • Thiago Monteiro disse:

    Bom dia André,

    Parabéns pela aula.
    Fiz tudo conforme no exemplo, porém ao fazer download de fotos a memoria vai subindo no gerenciador de tarefas. O que pode estar fazendo para assim que realizar o download não acontecer isso, mesmo utilizando os using tudo igual.
    Se puder me ajudar agradeço, obrigado.

    • andrealveslima disse:

      Olá Thiago!

      Estranho hein.. Deve estar faltando “using” em algum lugar.. Como é que ficou o seu código final?

      Abraço!
      André Lima

      • Thiago Monteiro disse:

        André, fiz um resumo do código, ficou assim.

        downloadDrive(nome, pastaParent, pastaDados);

        public void downloadDrive(string nome, string pastaParent, string pastaDados)
        {
        var credenciais = Autenticar();

        using (var servico = AbrirServico(credenciais))
        {
        Download(servico, nome, pastaDados, pastaParent);
        }
        }

        private static void Download(Google.Apis.Drive.v3.DriveService servico, string nome, string destino, string pastaParent)
        {
        var ids = ProcurarArquivoId(servico, nome, pastaParent);
        if (ids != null && ids.Any())
        {
        var request = servico.Files.Get(ids.First());
        using (var stream = new System.IO.FileStream(destino, System.IO.FileMode.Create, System.IO.FileAccess.Write))
        {
        request.Download(stream);
        }
        }
        else
        {
        Console.WriteLine(“Arquivo não encontrado”);
        }
        }

        • andrealveslima disse:

          Olá Thiago!

          Estranho hein.. Aparentemente está tudo OK, com os “usings” no lugar certo.. Pensei que talvez o retorno do método “Files.Get” pudesse ser IDisposable, mas pelo que vi no código da biblioteca, não é..

          Você tem certeza que a memória está subindo por causa do download?

          Abraço!
          André Lima

  • Eduardo Santana disse:

    Olá André,
    Excelente artigo, muito bem escrito e fácil de entender.
    Me ajudou muito!

  • Guilherme machado disse:

    fiz td conforme, mas meu programa não faz upload no google drive, ele só faz download e listagem de arquivo .
    será algum problema com permissao
    o codigo corre normal mas o arquivo não vai para la .

    • andrealveslima disse:

      Olá Guilherme!

      Estranho hein.. Você ainda está com esse problema ou conseguiu resolver? Parece problema de permissão mesmo, uma vez que você consegue listar os arquivos, mas não consegue salvar..

      Abraço!
      André Lima

  • Sanderson Corrêa disse:

    Olá. o projeto funcionou perfeitamente, mas preciso desse serviço em um Windows Service, mais especificamente o Upload de arquivo, mas o serviço para na autenticação (não abre o navegador), como faço para funcionar? Tem como?

    • andrealveslima disse:

      Olá Sanderson!

      Difícil hein.. Como o Google Drive precisa da interface do browser para fazer a autenticação a primeira vez, vai ser difícil conseguir com Windows Service.. Uma opção seria habilitar a opção no seu Windows Service para que ele possa interagir com o desktop (essa opção fica na aba Log On das propriedades do serviço).. Uma vez autenticado, você pode desabilitar essa opção novamente..

      Outra alternativa seria fazer a autenticação uma vez fora do Windows Service e, uma vez autenticado, colocar a pasta com os arquivos de credenciais na pasta do Windows Service..

      Abraço!
      André Lima

  • felipe disse:

    gostei da iniciativa e me ajudou muito com meu projeto!

  • Diogo disse:

    Tem como eu compartilhar o arquivo que foi realizado o upload e retornar somente as urls dos arquivos já compartilhados?

  • Renan disse:

    Olá André
    Estou passando aqui para agradecer pelo post e ótimo site que tem. Está me ajudando bastante. Um abraço!

  • Leo Vitor disse:

    Olá André achei seu post sensacional e muito bem explicado.
    Queria saber se vc consegue me auxiliar com algumas questões que fiquei na dúvida.
    A permissão que aparece quando executamos é para acesso ao google drive do próprio usuário, no meu caso estou criando uma aplicação desktop que irá realizar backup de algumas informações do servidor do meu cliente e irá subir para o drive da empresa, nesse caso eu consigo configurar a permissão de alguma forma internamente?

    • andrealveslima disse:

      Olá Leo!

      Você tem que fazer a autenticação uma vez e aí as informações de autenticação serão salvas na pasta da aplicação.. Aí você pode distribuir esses arquivos de credenciais junto com a aplicação e o usuário não terá que autenticar mais..

      Abraço!
      André Lima

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *