0

I am trying to upload files to my own google drive. What I did is 1. Created project on Google drive 2. Created credential for service account 3. Created security json for one user and gave user permission as owner Now using email provided by service for the user and downloaded json file, tried to upload a file/create folder. There are no errors and I am getting back file id.

However, when I check it on my drive, I do not see the uploaded file. here is my code:

using Google.Apis.Auth.OAuth2;
using Google.Apis.Drive.v2;
using Google.Apis.Drive.v2.Data;
using Google.Apis.Services;
using Google.Apis.Util.Store;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Google.Apis.Auth;
public void GetService()
        {
            string filename = "dheerajsecudata.json";
            string email = "dheeraj-588@secudata.iam.gserviceaccount.com";
            var service = AuthenticateServiceAccount(email, filename);
            CreateFolder("BlahBlah", service);
            var fileMetadata = new Google.Apis.Drive.v2.Data.File()
            {
                Title = "BrainData/bpl1.jpg"
            };
            FilesResource.InsertMediaUpload request;
            using (var stream = new System.IO.FileStream(@"D:/bpl1.jpg",
                                    System.IO.FileMode.Open))
            {
                request = service.Files.Insert(
                    fileMetadata, stream, "image/jpeg");
                request.Fields = "id";
                request.Upload();
            }
            var file = request.ResponseBody;
            Console.WriteLine("File ID: " + file.Id);//Getting ID but no folder / files on drive
        }
        private static void CreateFolder(string folderName, DriveService service)
        {
            var fileMetadata = new Google.Apis.Drive.v2.Data.File()
            {
                Title = folderName,
                MimeType = "application/vnd.google-apps.folder"
            };
            var request = service.Files.Insert(fileMetadata);
            request.Fields = "id";
            var file = request.Execute();
            Console.WriteLine("Folder ID: " + file.Id);

        }
        public static DriveService AuthenticateServiceAccount(string serviceAccountEmail, string serviceAccountCredentialFilePath)
        {
            try
            {
                if (string.IsNullOrEmpty(serviceAccountCredentialFilePath))
                    throw new Exception("Path to the service account credentials file is required.");
                if (!System.IO.File.Exists(serviceAccountCredentialFilePath))
                    throw new Exception("The service account credentials file does not exist at: " + serviceAccountCredentialFilePath);
                if (string.IsNullOrEmpty(serviceAccountEmail))
                    throw new Exception("ServiceAccountEmail is required.");

                // These are the scopes of permissions you need. It is best to request only what you need and not all of them
                //string[] scopes = new string[] { AnalyticsReportingService.Scope.Analytics };             // View your Google Analytics data
                string[] scopes = {  DriveService.Scope.Drive, DriveService.Scope.DriveFile };

                // For Json file
                if (Path.GetExtension(serviceAccountCredentialFilePath).ToLower() == ".json")
                {
                    GoogleCredential credential;
                    using (var stream = new FileStream(serviceAccountCredentialFilePath, FileMode.Open, FileAccess.Read))
                    {
                        credential = GoogleCredential.FromStream(stream)
                             .CreateScoped(scopes);
                    }

                    // Create the  Analytics service.
                    return new DriveService(new BaseClientService.Initializer()
                    {
                        HttpClientInitializer = credential,
                        ApplicationName = "Drive Service account Authentication Sample",
                    });
                }

                else
                {
                    throw new Exception("Unsupported Service accounts credentials.");
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("Create service account DriveService failed" + ex.Message);
                throw new Exception("CreateServiceAccountDriveFailed", ex);
            }
        }

1 Answers1

0
  • If you create a folder through a service account, this folder will be created on the drive of the service account, to which you do not have access
  • To resolve this issue, you need to to set up an impersonation
  • In other words, you need to set-up the service account in such a way, that it acts on your (or another domain user's) behalf, rather than on its own behalf
  • In this case, the folder will be created on the drive of the user impersonated by the service account
  • To set up impersonation, you need to grant to the service account grant G Suite domain-wide authority through the Admin console
  • In your code, you need to set up a subject (the email of the user to impersonate)
  • The Google documentation provides sample codes for delegating domain-wide authority in Java, Python and HTTP/REST
  • For C#, you can find sample code snippets e.g. on stackoverflow
ziganotschka
  • 25,866
  • 2
  • 16
  • 33
  • Thank you!! However for small projects without domain, it wont work. Getting domain is costly affair as far as small projects are concerned. I found solution by just giving permission. Now it works perfectly fine. However i am not able to delete files and folder which I had created earlier while testing. No problem, I can delete the project and create new one!! – Dheeraj Dhondalkar Dec 09 '19 at 16:41
  • I am glad you found a solution! However, even if you do not have a domain, I believe you can make the service account impersonate you? – ziganotschka Dec 09 '19 at 16:45
  • Yes, I am able to do that. Now I have one issue left to solve!! I am able to delete a file but not able to delete folder. What permission is required to service account to delete folder? I gave OWNER permission and able to delete file using service.File.Delete(id). but same doesnot work for folder – Dheeraj Dhondalkar Dec 10 '19 at 09:48
  • Did you also give owner permission of the folder to the service account? – ziganotschka Dec 10 '19 at 10:22