Google Drive SDK create file for user - c#

HelloI'm am currently trying to create a file under a specific user account.The user account is located within my Google Domain.For Oauth im using a service account.
The DriveService()
private static DriveService Service()
{
var certificate = new X509Certificate2(Constants.P12, "notasecret", X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(Constants.ServiceAccountEmail)
{
Scopes = new[] {
DriveService.Scope.Drive,
}
}.FromCertificate(certificate));
// Create the service.
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "MyApplicationName",
});
return service;
}
Creating a file
private static void CreateDriveDocument(string title)
{
Console.WriteLine("Google - Create New Document:" + Environment.NewLine);
File body = new File();
body.Title = title;
body.Description = "A test document";
body.MimeType = "text/plain";
byte[] byteArray = System.IO.File.ReadAllBytes(#"C:\myDoc.txt");
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
//Callin the service at "Service()"
FilesResource.InsertMediaUpload request = Service().Files.Insert(body, stream, "text/plain");
request.Upload();
File file = request.ResponseBody;
}
So here I create a File, since I authenticated with the ServiceAccount, thats where the File is uploaded.
The Question
I need to be able to Create/Copy this file to a specific user withing
my domain. And make that user owner of the file.
All help is appreciated.
Old post Reference
TransferOwnership Using Google SDK

I'll go with Marcel Balk anwser.
This way we will use impersonation!
we can use the service account to authenticate, then use any email account in our domain and upload files.
The uploaded files will be visible in the users Drive under My Files (not Shared with me!)
Files also are owned by the impersonated account.
Tested in a little console app:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Services;
namespace UseWebServiceMethod
{
class Program
{
// Goto https://admin.google.com/AdminHome?chromeless=1#OGX:ManageOauthClients
// Login met admin account => ****#***.***
// Add/edit Client Name (Use Client ID of service account here) => 2***8.apps.googleusercontent.com
// One or More API Scopes => https://www.googleapis.com/auth/drive
public const string ImpersonatedAccountEmail = "****#***.***";
public const string ServiceAccountEmail = "2******8#developer.gserviceaccount.com";
public const string Key = #"C:\Users\Wouter\Desktop\GoogleTester\GoogleTester\A****c.p12";
public const string FileToUpload = #"C:\Users\Wouter\Desktop\GoogleTester\GoogleTester\whakingly.txt";
public const string ApplicationName = "A***l";
static void Main()
{
var certificate = new X509Certificate2(Key, "notasecret", X509KeyStorageFlags.Exportable);
var initializer = new ServiceAccountCredential.Initializer(ServiceAccountEmail)
{
Scopes = new[] { DriveService.Scope.Drive },
User = ImpersonatedAccountEmail
};
var credential = new ServiceAccountCredential(initializer.FromCertificate(certificate));
var driveService = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName
});
// Show all files
var list = driveService.Files.List().Execute();
if (list.Items != null)
foreach (var fileItem in list.Items)
{
Console.WriteLine(fileItem.Title + " - " + fileItem.Description);
}
Console.WriteLine("Press Enter to continue.");
Console.ReadLine();
// Upload a new file
File body = new File();
body.Title = "whakingly.txt";
body.Description = "A whakingly (that a new word I created just there) file thats uploaded with impersonation";
body.MimeType = "text/plain";
byte[] byteArray = System.IO.File.ReadAllBytes(FileToUpload);
var stream = new System.IO.MemoryStream(byteArray);
FilesResource.InsertMediaUpload request = driveService.Files.Insert(body, stream, "text/plain");
request.Upload();
File file = request.ResponseBody;
Console.WriteLine("Press Enter to continue.");
Console.ReadLine();
// Show all files
var list2 = driveService.Files.List().Execute();
if (list2.Items != null)
foreach (var fileItem in list2.Items)
{
Console.WriteLine(fileItem.Title + " - " + fileItem.Description);
}
Console.WriteLine("Press Enter to continue.");
Console.ReadLine();
}
}
}

You can easily do this by adding the user to the code.
See the user i added.
private static DriveService Service()
{
var certificate = new X509Certificate2(Constants.P12, "notasecret",X509KeyStorageFlags.Exportable);
var credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(Constants.ServiceAccountEmail)
{
Scopes = new[] {DriveService.Scope.Drive},
User="someuser#somedomain.someextension" //Add this to your code!
}.FromCertificate(certificate));
// Create the service.
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "MyApplicationName",
});
return service;
}
Then go to admin.google.com --> Security --> Advance settings --> Manage oauth client access
Add the client id to the client name and add your scope (http://www.googleapis.com/auth/drive) to the "One or More API Scopes field"

Related

C# Google Drive API Empty Files List

I want to get a list of names of files from Google Drive but I get an empty list each time
I created a project on Google Console
I enabled Google Drive API
I created a user in OAuth consent screen
I created credentials OAuth 2.0 Client IDs and downloaded it as json
namespace ConsoleApp4
{
class Program
{
static string[] Scopes = { DriveService.Scope.Drive };
static string ApplicationName = "TestGoogleDriveAPI";
private static UserCredential GetCredentials()
{
using (var stream = new FileStream("credentials.json", FileMode.Open, FileAccess.Read))
{
// The file token.json stores the user's access and refresh tokens, and is created
// automatically when the authorization flow completes for the first time.
string credPath = Directory.GetCurrentDirectory();
credPath = Path.Combine(credPath, "drive-dot-net-quickstart.json");
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, false)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
return credential;
}
}
static void Main(string[] args)
{
UserCredential credential = GetCredentials();
// Create Drive API service.
var service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
// Define parameters of request.
FilesResource.ListRequest listRequest = service.Files.List();
//listRequest.Q = "name contains 'EMR_backup_' and createdTime > '2020-12-01T12:00:00' and modifiedTime > '2021-07-01T12:00:00'";
//listRequest.Q = "parents in '10ybGwqq7J_GbA7JvG6C8aiTFNRsdzdk7'";
//listRequest.PageSize = 10;
//listRequest.Fields = "nextPageToken, files(id, name)";
// List files.
//FileList result = listRequest.Execute();
IList<Google.Apis.Drive.v3.Data.File> files = listRequest.Execute().Files;
if (files != null && files.Count > 0)
{
foreach (var file in files)
{
Console.WriteLine("{0} ({1})", file.Name, file.Id);
}
}
else
{
Console.WriteLine("No files found.");
}
Console.Read();
}
}
}

How I upload mp3 file in Google drive using C# in MVC

I have successfully uploaded image file in google drive using C#. But i am facing problem in uploading mp3 file on drive.
How I upload mp3 file in Google drive using C# in MVC?
this my Code for save file:
public ServieResponse SaveFileOnGoogleDrive(string url)
{
//string url = string.Empty; ; ;
//string[] scopes = new string[] { DriveService.Scope.Drive,
// DriveService.Scope.DriveFile};
string[] scopes = new string[] { DriveService.Scope.Drive,
DriveService.Scope.DriveAppdata,
//DriveService.Scope.DriveAppsReadonly,
DriveService.Scope.DriveFile,
DriveService.Scope.DriveMetadataReadonly,
DriveService.Scope.DriveReadonly,
DriveService.Scope.DriveScripts };
var clientId = "xxxxxx"; // From https://console.developers.google.com
var clientSecret = "xxxxxxx";
// From https://console.developers.google.com
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret
},
scopes,
Environment.UserName,
CancellationToken.None,
new FileDataStore("MyAppsToken")).Result;
//Once consent is recieved, your token will be stored locally on the AppData directory, so that next time you wont be prompted for consent.
DriveService service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "CTM",
});
string filePath = WebConfigurationManager.AppSettings["filPath"];
filePath = HttpContext.Current.Server.MapPath(filePath) + url;
uploadFile(service, filePath, "", "");
// service.HttpClient.Timeout = TimeSpan.FromMinutes(100);
//Long Operations like file uploads might timeout. 100 is just precautionary value, can be set to any reasonable value depending on what you use your service for.
//return Json(new { result = "abc" }, JsonRequestBehavior.AllowGet);
ServieResponse ob = new ServieResponse();
ob.ResponseMsg = "Success";
return ob;
}
Now my code is working fine. Updated code is:
public ServieResponse SaveFileOnGoogleDrive(string url)
{
//string url = string.Empty; ; ;
//string[] scopes = new string[] { DriveService.Scope.Drive,
// DriveService.Scope.DriveFile};
string[] scopes = new string[] { DriveService.Scope.Drive,
DriveService.Scope.DriveAppdata,
//DriveService.Scope.DriveAppsReadonly,
DriveService.Scope.DriveFile,
DriveService.Scope.DriveMetadataReadonly,
DriveService.Scope.DriveReadonly,
DriveService.Scope.DriveScripts };
var clientId = "65675933715-poet7f7dhjhrmccmalhb41pltho7tusr.apps.googleusercontent.com"; // From https://console.developers.google.com
var clientSecret = "D8USyz3Pf82wOMi6l2pJehjx";
// From https://console.developers.google.com
// here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
var credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets
{
ClientId = clientId,
ClientSecret = clientSecret
},
scopes,
Environment.UserName,
CancellationToken.None,
new FileDataStore("MyAppsToken")).Result;
//Once consent is recieved, your token will be stored locally on the AppData directory, so that next time you wont be prompted for consent.
DriveService service = new DriveService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "CTM",
});
string filePath = WebConfigurationManager.AppSettings["filPath"];
filePath = HttpContext.Current.Server.MapPath(filePath) + url;
uploadFile(service, filePath);
ServieResponse ob = new ServieResponse();
ob.ResponseMsg = "Success";
return ob;
}
public static void uploadFile(DriveService _service, string _uploadFile)
{
if (System.IO.File.Exists(_uploadFile))
{
var body = new Google.Apis.Drive.v3.Data.File();
//File body = new File();
body.Name = System.IO.Path.GetFileName(_uploadFile);
//body.Description = _descrp;
body.MimeType = GetMimeType(_uploadFile);
// body.Parents = new List<ParentReference>() { new ParentReference() { Id = _parent } };
FilesResource.CreateMediaUpload request;
try
{
using (var stream = new System.IO.FileStream(_uploadFile, System.IO.FileMode.Open))
{
request = _service.Files.Create(body, stream, body.MimeType);
request.Fields = "id";
request.Upload();
}
var file = request.ResponseBody;
var fili = file.Id;
}
catch (Exception e)
{
}
}
else
{
}
}
private static string GetMimeType(string fileName)
{
string mimeType = "application/unknown";
string ext = System.IO.Path.GetExtension(fileName).ToLower();
Microsoft.Win32.RegistryKey regKey = Microsoft.Win32.Registry.ClassesRoot.OpenSubKey(ext);
if (regKey != null && regKey.GetValue("Content Type") != null)
mimeType = regKey.GetValue("Content Type").ToString();
return mimeType;
}

Send Google Mail in C# failed because of 403 Insufficient permissions

I created a console application which sends an email to an address, it shows like:
private static string[] Scopes = { GmailService.Scope.GmailCompose, GmailService.Scope.GmailSend };
private static string ApplicationName = "Gmail API Quickstart";
private const string SUBJECT = "Some simple subject";
private static string[] emails = new string[] { "teodorescumihail2008#live.com" };
static void Main(string[] args)
{
UserCredential credential;
using (var stream =
new FileStream("client_secret.json", FileMode.Open, FileAccess.Read))
{
string credPath = Environment.GetFolderPath(
Environment.SpecialFolder.Personal);
credPath = Path.Combine(credPath, ".credentials/gmail-dotnet-quickstart.json");
credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
GoogleClientSecrets.Load(stream).Secrets,
Scopes,
"user",
CancellationToken.None,
new FileDataStore(credPath, true)).Result;
Console.WriteLine("Credential file saved to: " + credPath);
}
// Create Gmail API service.
var service = new GmailService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = ApplicationName,
});
var msg = new AE.Net.Mail.MailMessage
{
Subject = SUBJECT,
Body = "Test body",
From = new MailAddress("teodorescumihail2008#gmail.com")
};
msg.To.Add(new MailAddress("teodorescumihail2008#live.com"));
StringWriter sw = new StringWriter();
msg.Save(sw);
var result = service.Users.Messages.Send(new Message
{
Raw = Base64UrlEncode(sw.ToString())
}, "me").Execute();
Console.Read();
}
private static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
// Special "url-safe" base64 encode.
return Convert.ToBase64String(inputBytes)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", "");
}
When execute sending email, I received:
Where is my mistake ?
I assumed you changed your scope in the code without reauthorize/getting a new credential file from Gmail. The problem is GmailAPI does not know that your scope is updated. You have to reauthorize your app in GmailAPI by deleting your app permission and regenerate your credentials.json so that your scope is updated on GmailAPI.
To delete your app permission: click here

How To create an instance of Google BaseClientService.Initializer

I want to know how to create an instance of Google BaseClientService.Initializer. I need to use the BaseClientService.Initializer to create the GmailService instance, and then use this GmailService instance to create an UsersResource instance.
Google.Apis.Services.BaseClientService.Initializer initializer = new BaseClientService.Initializer();
initializer.ApiKey = "MyApiKey";
initializer.ApplicationName = "MyProject";
initializer.DefaultExponentialBackOffPolicy = Google.Apis.Http.ExponentialBackOffPolicy.None;
Google.Apis.Gmail.v1.GmailService gmailService = new GmailService(initializer);
Google.Apis.Gmail.v1.UsersResource usersResource = new UsersResource(gmailService);
UsersResource.MessagesResource messagesResource = usersResource.Messages;
First go to the link bellow and open an application in your google account.
once you run the code you'll get exception for the first time, given you an address to go and enable the API in your google account.
https://console.developers.google.com/apis/dashboard?project=super-pharm-log-notifications
static string[] Scopes = { GmailService.Scope.GmailCompose, GmailService.Scope.GmailSend, GmailService.Scope.GmailInsert };
static private BaseClientService.Initializer initializeGmailAccountServices()
{
string appRoot = null;
if (System.Web.HttpContext.Current == null)
{
appRoot = Environment.CurrentDirectory;
}
else
{
appRoot = System.Web.HttpContext.Current.Server.MapPath(#"~\");
}
string path = Path.Combine(appRoot, DBConstants.GMAIL_CREDENTIALS_PATH);
UserCredential credential;
using (var stream = new FileStream(path, FileMode.Open, FileAccess.Read))
{
ClientSecrets secrets = GoogleClientSecrets.Load(stream).Secrets;
var t = GoogleWebAuthorizationBroker.AuthorizeAsync(secrets, Scopes, "user", CancellationToken.None);
t.Wait();
credential = t.Result;
}
return= new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "your application name",
};
}
private static string Base64UrlEncode(string input)
{
var inputBytes = System.Text.Encoding.UTF8.GetBytes(input);
// Special "url-safe" base64 encode.
return Convert.ToBase64String(inputBytes)
.Replace('+', '-')
.Replace('/', '_')
.Replace("=", "");
}

Upload file using Service Account to Google Cloud Storage bucket that was generated in Google Merchant Center

I was able to upload a file to the Google Cloud Storage bucket with the following code. I created the bucket manually.
String serviceAccountEmail = "xxxxxxxxxxxx-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx#developer.gserviceaccount.com";
var certificate = new X509Certificate2(#"C:\...\projectname-xxxxxxxxxxxx.p12", "notasecret", X509KeyStorageFlags.Exportable);
var scopes = new[] { #"https://www.googleapis.com/auth/devstorage.full_control" };
ServiceAccountCredential credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromCertificate(certificate));
StorageService service = new StorageService(new BaseClientService.Initializer()
{
HttpClientInitializer = credential,
ApplicationName = "Shipment Feed",
});
var bucketToUpload = "bucket-created-by-me";
var newObject = new Google.Apis.Storage.v1.Data.Object()
{
Bucket = bucketToUpload,
Name = "ShipmentFeed.txt"
};
FileStream fileStream = null;
var path = #"C:\...\file.txt";
fileStream = new FileStream(path, FileMode.Open);
var uploadRequest = new ObjectsResource.InsertMediaUpload(service, newObject,
bucketToUpload, fileStream, "text/plain");
uploadRequest.Upload();
Now I ran into the problem when I tried to upload the file to the bucket, generated by Google Merchant Center, for the same Google account. I used the code above by simply changing the bucket name to the value provided by the Google Merchant center from Settings->Google Cloud Storage
var bucketToUpload = "merchantxxxxxxx";
This procedure did not get the file uploaded to the bucket (tested with gsutil - bucket exists in my project but is empty). Why can't I upload the file?
Your code does not authorize the access to Google Cloud Storage.
After you create ServiceAccountCredential, you must get Access Token by calling:
ServiceAccountCredential sac = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = scopes
}.FromCertificate(certificate));
var cts = new CancellationToken();
var response = sac.RequestAccessTokenAsync(cts).Result;
If the response is true, your ServiceAccountCredential object will have ServiceAccountCredential.Token.AccessToken set.
Then, when you create your uploadRequest, you must provide the AccessToken you obtained:
var uploadRequest = new ObjectsResource.InsertMediaUpload(service, newObject,
bucketToUpload, fileStream, "text/plain");
uploadRequest.OauthToken = sac.Token.AccessToken;
And finally call:
uploadRequest.Upload();

Categories