Sunteți pe pagina 1din 29

Utilizando a API do Google Drive no C# e

VB.NET
andrealveslima | .NET, Software Development | 154
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;

1 using (var stream = new System.IO.FileStream("client_id.json",


2 System.IO.FileMode.Open, System.IO.FileAccess.Read))
3 {
4 var diretorioAtual =
5 System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExe
6 cutingAssembly().Location);
7 var diretorioCredenciais =
8 System.IO.Path.Combine(diretorioAtual, "credential");
9
10 credenciais =
11 Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsy
12 nc(
13 Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(stre
14 am).Secrets,
15 new[]
16 { Google.Apis.Drive.v3.DriveService.Scope.DriveReadonly },
17 "user",
18 System.Threading.CancellationToken.None,
19 new
20 Google.Apis.Util.Store.FileDataStore(diretorioCredenciais,
true)).Result;
}

return credenciais;
}
1 ' VB.NET
2 Private Function Autenticar() As
3 Google.Apis.Auth.OAuth2.UserCredential
4 Dim Credenciais As Google.Apis.Auth.OAuth2.UserCredential
5
6 Using Stream = New System.IO.FileStream("client_id.json",
7 System.IO.FileMode.Open, System.IO.FileAccess.Read)
8 Dim DiretorioAtual =
9 System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExe
10 cutingAssembly().Location)
11 Dim DiretorioCredenciais =
System.IO.Path.Combine(DiretorioAtual, "credential")

Credenciais =
Google.Apis.Auth.OAuth2.GoogleWebAuthorizationBroker.AuthorizeAsy
nc(
Google.Apis.Auth.OAuth2.GoogleClientSecrets.Load(Stre
12
am).Secrets,
13
New String()
14 {Google.Apis.Drive.v3.DriveService.Scope.DriveReadonly},
15 "user",
16 System.Threading.CancellationToken.None,
17 New
18 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#
1 private static Google.Apis.Drive.v3.DriveService
2 AbrirServico(Google.Apis.Auth.OAuth2.UserCredential credenciais)
3{
4 return new Google.Apis.Drive.v3.DriveService(new
5 Google.Apis.Services.BaseClientService.Initializer()
6 {
7 HttpClientInitializer = credenciais
8 });
}
1 ' VB.NET
2 Private Function AbrirServico(Credenciais As
3 Google.Apis.Auth.OAuth2.UserCredential) As
Google.Apis.Drive.v3.DriveService
Return New Google.Apis.Drive.v3.DriveService(New
4 Google.Apis.Services.BaseClientService.Initializer() With {
5 .HttpClientInitializer = Credenciais
6 })
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:
1 // C#
2 var credenciais = Autenticar();
3
4 using (var servico = AbrirServico(credenciais))
5{
6}
1 ' VB.NET
2 Dim Credenciais = Autenticar()
3
4 Using Servico = AbrirServico(Credenciais)
5
6 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:
1 // C#
2 private static void
3 ListarArquivos(Google.Apis.Drive.v3.DriveService servico)
4 {
5 var request = servico.Files.List();
6 request.Fields = "files(id, name)";
7 var resultado = request.Execute();
var arquivos = resultado.Files;
8
9
if (arquivos != null && arquivos.Any())
10
{
11 foreach (var arquivo in arquivos)
12 {
13 Console.WriteLine(arquivo.Name);
14 }
15 }
16 }
' VB.NET
1
Private Sub ListarArquivos(Servico As
2
Google.Apis.Drive.v3.DriveService)
3
Dim Request = Servico.Files.List()
4
Request.Fields = "files(id, name)"
5 Dim Resultado = Request.Execute()
6 Dim Arquivos = Resultado.Files
7
8 If Arquivos IsNot Nothing AndAlso Arquivos.Any() Then
9 For Each Arquivo In Arquivos
10 Console.WriteLine(Arquivo.Name)
11 Next
12 End If
13 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:
1 // C#
2 Console.WriteLine("Listagem");
3 ListarArquivos(servico);
4 Console.WriteLine("Fim Listagem");
5 Console.ReadLine();
1 ' VB.NET
2 Console.WriteLine("Listagem")
3 ListarArquivos(Servico)
4 Console.WriteLine("Fim Listagem")
5 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:
1 // C#
2 request.PageSize = 1000;
3 var resultado = request.Execute();
1 ' VB.NET
2 Request.PageSize = 1000
3 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:
1 // C#
2 request.Q = "trashed=false";
1 ' VB.NET
2 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:
1 // C#
2 private static void
3 ListarArquivosPaginados(Google.Apis.Drive.v3.DriveService
4 servico, int arquivosPorPagina)
5 {
6 var request = servico.Files.List();
7 request.Fields = "nextPageToken, files(id, name)";
8 //request.Q = "trashed=false";
// Default 100, máximo 1000.
9 request.PageSize = arquivosPorPagina;
var resultado = request.Execute();
10
var arquivos = resultado.Files;
11
12
while (arquivos != null && arquivos.Any())
13
{
14
foreach (var arquivo in arquivos)
15
{
16
Console.WriteLine(arquivo.Name);
17
}
18
19
if (resultado.NextPageToken != null)
20 {
21 Console.WriteLine("Digite ENTER para ir para a
22 próxima página");
23 Console.ReadLine();
24 request.PageToken = resultado.NextPageToken;
25 resultado = request.Execute();
26 arquivos = resultado.Files;
27 }
28 else
29 {
30 arquivos = null;
31 }
32 }
}
1 ' VB.NET
2 Private Sub ListarArquivosPaginados(Servico As
3 Google.Apis.Drive.v3.DriveService, ArquivosPorPagina As Integer)
4 Dim Request = Servico.Files.List()
5 Request.Fields = "nextPageToken, files(id, name)"
6 'Request.Q = "trashed=false"
7 ' Default 100, máximo 1000.
8 Request.PageSize = ArquivosPorPagina
9 Dim Resultado = Request.Execute()
10 Dim Arquivos = Resultado.Files
11
12 While Arquivos IsNot Nothing AndAlso Arquivos.Any()
13 For Each arquivo In Arquivos
14 Console.WriteLine(arquivo.Name)
15 Next
16
17 If Resultado.NextPageToken IsNot Nothing Then
18 Console.WriteLine("Digite ENTER para ir para a
19 próxima página")
20 Console.ReadLine()
21 Request.PageToken = Resultado.NextPageToken
22 Resultado = Request.Execute()
23 Arquivos = Resultado.Files
24 Else
25 Arquivos = Nothing
26 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:
1 // C#
2 Console.Clear();
3 Console.WriteLine("Listagem paginada");
4 ListarArquivosPaginados(servico, 10);
5 Console.WriteLine("Fim Listagem paginada");
6 Console.ReadLine();
1 ' VB.NET
2 Console.Clear()
3 Console.WriteLine("Listagem paginada")
4 ListarArquivosPaginados(Servico, 10)
5 Console.WriteLine("Fim Listagem paginada")
6 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#
1 private static void
2 CriarDiretorio(Google.Apis.Drive.v3.DriveService servico, string
3 nomeDiretorio)
4{
5 var diretorio = new Google.Apis.Drive.v3.Data.File();
6 diretorio.Name = nomeDiretorio;
7 diretorio.MimeType = "application/vnd.google-apps.folder";
8 var request = servico.Files.Create(diretorio);
9 request.Execute();
}
' VB.NET
1
Private Sub CriarDiretorio(Servico As
2
Google.Apis.Drive.v3.DriveService, NomeDiretorio As String)
3 Dim Diretorio = New Google.Apis.Drive.v3.Data.File()
4 Diretorio.Name = NomeDiretorio
5 Diretorio.MimeType = "application/vnd.google-apps.folder"
6 Dim Request = Servico.Files.Create(Diretorio)
7 Request.Execute()
8 End Sub
Para criarmos um diretório chamado “NovoDiretorio” temos que fazer a seguinte chamada dentro
do nosso bloco “using“:
1 // C#
2 Console.Clear();
3 Console.WriteLine("Criar diretório");
4 CriarDiretorio(servico, "NovoDiretorio");
5 Console.WriteLine("Fim Criar diretório");
6 Console.ReadLine();
1 ' VB.NET
2 Console.Clear()
3 Console.WriteLine("Criar diretório")
4 CriarDiretorio(Servico, "NovoDiretorio")
5 Console.WriteLine("Fim Criar diretório")
6 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#
1 private static string[]
2 ProcurarArquivoId(Google.Apis.Drive.v3.DriveService servico,
3 string nome, bool procurarNaLixeira = false)
4 {
5 var retorno = new List<string>();
6
7 var request = servico.Files.List();
8 request.Q = string.Format("name = '{0}'", nome);
9 if (!procurarNaLixeira)
10 {
11 request.Q += " and trashed = false";
12 }
13 request.Fields = "files(id)";
14 var resultado = request.Execute();
15 var arquivos = resultado.Files;
16
17 if (arquivos != null && arquivos.Any())
18 {
19 foreach (var arquivo in arquivos)
20 {
21 retorno.Add(arquivo.Id);
22 }
23 }
24
25 return retorno.ToArray();
}
1 ' VB.NET
2 Private Function ProcurarArquivoId(Servico As
3 Google.Apis.Drive.v3.DriveService, Nome As String, Optional
4 ProcurarNaLixeira As Boolean = False) As String()
5 Dim Retorno = New List(Of String)()
6
7 Dim Request = Servico.Files.List()
8 Request.Q = String.Format("name = '{0}'", Nome)
9 If Not ProcurarNaLixeira Then
10 Request.Q += " and trashed = false"
11 End If
12 Request.Fields = "files(id)"
13 Dim Resultado = Request.Execute()
14 Dim Arquivos = Resultado.Files
15
16 If Arquivos IsNot Nothing AndAlso Arquivos.Any() Then
17 For Each Arquivo In Arquivos
18 Retorno.Add(Arquivo.Id)
19 Next
20 End If
21
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#
1
private static void DeletarItem(Google.Apis.Drive.v3.DriveService
2
servico, string nome)
3
{
4
var ids = ProcurarArquivoId(servico, nome);
5
if (ids != null && ids.Any())
6 {
7 foreach (var id in ids)
8 {
9 var request = servico.Files.Delete(id);
10 request.Execute();
11 }
12 }
13 }
' VB.NET
1
Private Sub DeletarItem(Servico As
2
Google.Apis.Drive.v3.DriveService, Nome As String)
3
Dim Ids = ProcurarArquivoId(Servico, Nome)
4 If Ids IsNot Nothing AndAlso Ids.Any() Then
5 For Each Id In Ids
6 Dim Request = Servico.Files.Delete(Id)
7 Request.Execute()
8 Next
9 End If
10 End Sub
Por fim, a chamada para deletarmos o diretório “NovoDiretorio” que criamos anteriormente ficaria
da seguinte maneira:
1 // C#
2 Console.Clear();
3 Console.WriteLine("Deletar item");
4 DeletarItem(servico, "NovoDiretorio");
5 Console.WriteLine("Fim Deletar item");
6 Console.ReadLine();
1 ' VB.NET
2 Console.Clear()
3 Console.WriteLine("Deletar item")
4 DeletarItem(Servico, "NovoDiretorio")
5 Console.WriteLine("Fim Deletar item")
6 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)
1
{
2
var arquivo = new Google.Apis.Drive.v3.Data.File();
3
arquivo.Name = System.IO.Path.GetFileName(caminhoArquivo);
4
arquivo.MimeType =
5 MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(cam
6 inhoArquivo));
7 using (var stream = new System.IO.FileStream(caminhoArquivo,
8 System.IO.FileMode.Open, System.IO.FileAccess.Read))
9 {
10 var request = servico.Files.Create(arquivo, stream,
11 arquivo.MimeType);
12 request.Upload();
}
}
1 ' VB.NET
2 Private Sub Upload(Servico As Google.Apis.Drive.v3.DriveService,
3 CaminhoArquivo As String)
4 Dim Arquivo = New Google.Apis.Drive.v3.Data.File()
5 Arquivo.Name = System.IO.Path.GetFileName(CaminhoArquivo)
6 Arquivo.MimeType =
7 MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(Cam
inhoArquivo))
Using Stream = New System.IO.FileStream(CaminhoArquivo,
System.IO.FileMode.Open, System.IO.FileAccess.Read)
8 Dim Request = Servico.Files.Create(Arquivo, Stream,
9 Arquivo.MimeType)
10 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:
1 // C#
2 Console.Clear();
3 Console.WriteLine("Upload");
4 Upload(servico, "arquivo.txt");
5 Console.WriteLine("Fim Upload");
6 Console.ReadLine();
1 ' VB.NET
2 Console.Clear()
3 Console.WriteLine("Upload")
4 Upload(Servico, "arquivo.txt")
5 Console.WriteLine("Fim Upload")
6 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)
1{
var arquivo = new Google.Apis.Drive.v3.Data.File();
2
arquivo.Name = System.IO.Path.GetFileName(caminhoArquivo);
3
arquivo.MimeType =
4
MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(cam
5
inhoArquivo));
6
7
using (var stream = new System.IO.FileStream(caminhoArquivo,
8
System.IO.FileMode.Open, System.IO.FileAccess.Read))
9
{
10
var ids = ProcurarArquivoId(servico, arquivo.Name);
11 Google.Apis.Upload.ResumableUpload<Google.Apis.Drive.v3.D
12 ata.File, Google.Apis.Drive.v3.Data.File> request;
13
14 if (ids == null || !ids.Any())
15 {
16 request = servico.Files.Create(arquivo, stream,
17 arquivo.MimeType);
18 }
19 else
20 {
21 request = servico.Files.Update(arquivo, ids.First(),
22 stream, arquivo.MimeType);
23 }
24
request.Upload();
}
}
1 ' VB.NET
2 Private Sub Upload(Servico As Google.Apis.Drive.v3.DriveService,
3 CaminhoArquivo As String)
4 Dim Arquivo = New Google.Apis.Drive.v3.Data.File()
5 Arquivo.Name = System.IO.Path.GetFileName(CaminhoArquivo)
6 Arquivo.MimeType =
7 MimeTypes.MimeTypeMap.GetMimeType(System.IO.Path.GetExtension(Cam
8 inhoArquivo))
9
10 Using Stream = New System.IO.FileStream(CaminhoArquivo,
11 System.IO.FileMode.Open, System.IO.FileAccess.Read)
12 Dim Ids = ProcurarArquivoId(Servico, Arquivo.Name)
13 Dim Request As Google.Apis.Upload.ResumableUpload(Of
14 Google.Apis.Drive.v3.Data.File, Google.Apis.Drive.v3.Data.File)
15
16 If Ids Is Nothing OrElse Not Ids.Any() Then
17 Request = Servico.Files.Create(Arquivo, Stream,
18 Arquivo.MimeType)
19 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#
1 private static void Download(Google.Apis.Drive.v3.DriveService
2 servico, string nome, string destino)
3 {
4 var ids = ProcurarArquivoId(servico, nome);
5 if (ids != null && ids.Any())
6 {
7 var request = servico.Files.Get(ids.First());
8 using (var stream = new System.IO.FileStream(destino,
9 System.IO.FileMode.Create, System.IO.FileAccess.Write))
10 {
11 request.Download(stream);
12 }
13 }
}
' VB.NET
1 Private Sub Download(Servico As Google.Apis.Drive.v3.DriveService,
2 Nome As String, Destino As String)
3 Dim Ids = ProcurarArquivoId(Servico, Nome)
4 If Ids IsNot Nothing AndAlso Ids.Any() Then
5 Dim Request = Servico.Files.[Get](Ids.First())
6 Using Stream = New System.IO.FileStream(Destino,
7 System.IO.FileMode.Create, System.IO.FileAccess.Write)
8 Request.Download(Stream)
9 End Using
10 End If
End Sub
Para baixarmos o “arquivo.txt” que fizemos o upload na seção anterior, a chamada ficaria assim:
1 // C#
2 Console.Clear();
3 Console.WriteLine("Download");
4 Download(servico, "arquivo.txt", "arquivoBaixado.txt");
5 Console.WriteLine("Fim Download");
6 Console.ReadLine();
1 ' VB.NET
2 Console.Clear()
3 Console.WriteLine("Download")
4 Download(Servico, "arquivo.txt", "arquivoBaixado.txt")
5 Console.WriteLine("Fim Download")
6 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#
1 private static void
2 MoverParaLixeira(Google.Apis.Drive.v3.DriveService servico,
3 string nome)
4 {
5 var ids = ProcurarArquivoId(servico, nome);
6 if (ids != null && ids.Any())
7 {
8 foreach (var id in ids)
9 {
10 var arquivo = new Google.Apis.Drive.v3.Data.File();
11 arquivo.Trashed = true;
12 var request = servico.Files.Update(arquivo, id);
13 request.Execute();
14 }
15 }
}
' VB.NET
1
Private Sub MoverParaLixeira(Servico As
2
Google.Apis.Drive.v3.DriveService, Nome As String)
3
Dim Ids = ProcurarArquivoId(Servico, Nome)
4
If Ids IsNot Nothing AndAlso Ids.Any() Then
5 For Each Id In Ids
6 Dim Arquivo = New Google.Apis.Drive.v3.Data.File()
7 Arquivo.Trashed = True
8 Dim Request = Servico.Files.Update(Arquivo, Id)
9 Request.Execute()
10 Next
11 End If
12 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:
1 // C#
2 Console.Clear();
3 Console.WriteLine("Lixeira");
4 MoverParaLixeira(servico, "arquivo.txt");
5 Console.WriteLine("Fim Lixeira");
6 Console.ReadLine();
1 ' VB.NET
2 Console.Clear()
3 Console.WriteLine("Lixeira")
4 MoverParaLixeira(Servico, "arquivo.txt")
5 Console.WriteLine("Fim Lixeira")
6 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:
1 // C#
2 public class AppFlowMetadata :
3 Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
4 {
5 private static readonly
6 Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow flow =
7 new
8 Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow(new
9 Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow.Initial
10 izer
11 {
12 ClientSecrets = new
13 Google.Apis.Auth.OAuth2.ClientSecrets
14 {
15 ClientId = "SEU_ID",
16 ClientSecret = "SEU_SECRET"
17 },
18 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)
19 {
20 // In this sample we use the session to store the user
21 identifiers.
22 // That's not the best practice, because you should have
23 a logic to identify
24 // a user. You might want to use "OpenID Connect".
25 // You can read more about the protocol in the following
26 link:
27 //
28 https://developers.google.com/accounts/docs/OAuth2Login.
29 var user = controller.Session["user"];
30 if (user == null)
31 {
32 user = Guid.NewGuid();
33 controller.Session["user"] = user;
34 }
35 return user.ToString();
36
37 }

public override
Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow Flow
{
get { return flow; }
}
}
1 ' VB.NET
2 Public Class AppFlowMetadata
3 Inherits Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
4 Private Shared ReadOnly m_flow As
5 Google.Apis.Auth.OAuth2.Flows.IAuthorizationCodeFlow = New
6 Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow(New
7 Google.Apis.Auth.OAuth2.Flows.GoogleAuthorizationCodeFlow.Initial
8 izer() With {
9 .ClientSecrets = New
10 Google.Apis.Auth.OAuth2.ClientSecrets() With {
11 .ClientId = "SEU_ID",
12 .ClientSecret = "SEU_SECRET"
13 },
14 .Scopes = New String()
15 {Google.Apis.Drive.v3.DriveService.Scope.Drive},
16 .DataStore = New
17 Google.Apis.Util.Store.FileDataStore("Drive.Api.Auth.Store")
18 })
19
20 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
21
link:
22
'
23
https://developers.google.com/accounts/docs/OAuth2Login.
24
Dim user = controller.Session("user")
25 If user Is Nothing Then
26 user = Guid.NewGuid()
27 controller.Session("user") = user
28 End If
29 Return user.ToString()
30
31 End Function
32
33 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#
1 public class AuthCallbackController :
2 Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
3{
4 protected override Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
5 FlowData
6 {
7 get { return new AppFlowMetadata(); }
8 }
}
1 ' VB.NET
2 Public Class AuthCallbackController
3 Inherits
4 Google.Apis.Auth.OAuth2.Mvc.Controllers.AuthCallbackController
5 Protected Overrides ReadOnly Property FlowData() As
6 Google.Apis.Auth.OAuth2.Mvc.FlowMetadata
7 Get
8 Return New AppFlowMetadata()
End Get
9 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>
1 Index(System.Threading.CancellationToken cancellationToken)
2 {
3 var result = await new
4 Google.Apis.Auth.OAuth2.Mvc.AuthorizationCodeMvcApp(this, new
5 AppFlowMetadata()).
6 AuthorizeAsync(cancellationToken);
7
8 if (result.Credential != null)
9 {
10 var service = new Google.Apis.Drive.v3.DriveService(new
11 Google.Apis.Services.BaseClientService.Initializer
12 {
13 HttpClientInitializer = result.Credential,
14 ApplicationName = "ASP.NET MVC Sample"
15 });
16
17 ViewBag.Arquivos = ListarArquivos(service);
18
19 return View();
20 }
21 else
22 {
23 return new RedirectResult(result.RedirectUri);
}
}
1 ' VB.NET
2 Public Async Function Index(cancellationToken As
3 System.Threading.CancellationToken) As
4 System.Threading.Tasks.Task(Of ActionResult)
5 Dim result = Await New
6 Google.Apis.Auth.OAuth2.Mvc.AuthorizationCodeMvcApp(Me, New
7 AppFlowMetadata()).AuthorizeAsync(cancellationToken)
8
9 If result.Credential IsNot Nothing Then
10 Dim service = New Google.Apis.Drive.v3.DriveService(New
11 Google.Apis.Services.BaseClientService.Initializer() With {
12 .HttpClientInitializer = result.Credential,
13 .ApplicationName = "ASP.NET MVC Sample"})
14
15 ViewBag.Arquivos = ListarArquivos(service)
16
Return View()
Else
Return New RedirectResult(result.RedirectUri)
End If
End Function
E a view ficaria assim:
1 <!--C#-->
2 @{
3 ViewBag.Title = "Index";
4}
5 <h2>Index</h2>
6 @foreach (var item in ViewBag.Arquivos)
7{
8 <div>@item</div>
9 }
1 <!--VB.NET-->
2 @Code
3 ViewData("Title") = "Index"
4 End Code
5 <h2>Index</h2>
6 @For Each Item In ViewBag.Arquivos
7 @<div>@item</div>
8 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.

S-ar putea să vă placă și