0

The Google Drive API is not able to transfer ownership of a file which was uploaded from the API itself.

as per the API documentation, PUT needs to be used for transferring ownership. when I use it with the parameters required it returns existing permission back. doesn't update it with new owner.

if i use POST & the required parameters it throws 'The remote server returned an error: (400) Bad Request.'

I was able to change the ownership for the files that were NOT uploaded via API. the same which I use for the files which are uploaded from API. the owner doesn't change.

Is it a bug or I am doing something wrong?

-EDIT- if anyone wants details of file uploaded using API & file created via gdocs I can.

-EDIT2-

public bool UploadReportToGoogleDrive(Model model, byte[] ReportPDF_ByteArray, string ddlAddFilesFolder = "root", bool doNotify = true)
    {
        bool isErrorOccured = false;

        try
        {
            SingletonLogger.Instance.Info("UploadReportToGoogleDrive - start");
            FileList fileList = new FileList();
            Google.Apis.Drive.v2.Data.File uploadedFile = new Google.Apis.Drive.v2.Data.File();
            Permission writerPermission = new Permission();

            string accessToken = GetAccessToken();
            #region FIND  REPORT FOLDER
            string url = "https://www.googleapis.com/drive/v2/files?"
                + "access_token=" + accessToken
                + "&q=" + HttpUtility.UrlEncode("title='My Reports' and trashed=false and mimeType in 'application/vnd.google-apps.folder'")
                ;

            // Create POST data and convert it to a byte array.
            List<string> _postData = new List<string>();
            string postData = string.Join("", _postData.ToArray());

            try
            {
                WebRequest request = WebRequest.Create(url);
                string responseString = GDriveHelper.GetResponse(request);
                fileList = JsonConvert.DeserializeObject<FileList>(responseString);
                SingletonLogger.Instance.Info("UploadReportToGoogleDrive - folder search success");
            }
            catch (Exception ex)
            {
                SingletonLogger.Instance.Error("UploadReportToGoogleDrive\\FIND  REPORT FOLDER", ex);
                isErrorOccured = true;
            }
            #endregion FIND  REPORT FOLDER

            if (fileList.Items.Count == 0)
            {
                #region CREATE  REPORT FOLDER
                url = "https://www.googleapis.com/drive/v2/files?" + "access_token=" + accessToken;

                // Create POST data and convert it to a byte array.
                _postData = new List<string>();
                _postData.Add("{");
                _postData.Add("\"title\": \"" + "My Reports" + "\",");
                _postData.Add("\"description\": \"Uploaded with Google Drive API\",");
                _postData.Add("\"parents\": [{\"id\":\"" + "root" + "\"}],");
                _postData.Add("\"mimeType\": \"" + "application/vnd.google-apps.folder" + "\"");
                _postData.Add("}");
                postData = string.Join("", _postData.ToArray());

                try
                {
                    WebRequest request = WebRequest.Create(url);

                    byte[] byteArray = Encoding.UTF8.GetBytes(postData);
                    // Set the ContentType property of the WebRequest.
                    request.ContentType = "application/json";
                    // Set the ContentLength property of the WebRequest.
                    request.ContentLength = postData.Length;//byteArray.Length;
                    // Set the Method property of the request to POST.
                    request.Method = "POST";
                    // Get the request stream.
                    Stream dataStream = request.GetRequestStream();
                    // Write the data to the request stream.
                    dataStream.Write(byteArray, 0, byteArray.Length);
                    // Close the Stream object.
                    dataStream.Close();

                    string responseString = GDriveHelper.GetResponse(request);
                    Google.Apis.Drive.v2.Data.File ReportFolder = JsonConvert.DeserializeObject<Google.Apis.Drive.v2.Data.File>(responseString);
                    ;
                    ddlAddFilesFolder = ReportFolder.Id;
                    SingletonLogger.Instance.Info("UploadReportToGoogleDrive - folder creation success");
                }
                catch (Exception ex)
                {
                    SingletonLogger.Instance.Error("UploadReportToGoogleDrive\\CREATE  REPORT FOLDER", ex);
                    isErrorOccured = true;
                }
                #endregion CREATE  REPORT FOLDER
            }
            else
            {
                ddlAddFilesFolder = fileList.Items.FirstOrDefault().Id;
            }

            if (!isErrorOccured)
            {
                #region UPLOAD NEW FILE - STACKOVER FLOW
                //Createing the MetaData to send
                _postData = new List<string>();

                _postData.Add("{");
                _postData.Add("\"title\": \"" + "Report_" + model.id + "\",");
                _postData.Add("\"description\": \"" + " report of person - " + (model.borrowerDetails.firstName + " " + model.borrowerDetails.lastName) + "\",");

                _postData.Add("\"parents\": [{\"id\":\"" + ddlAddFilesFolder + "\"}],");
                _postData.Add("\"extension\": \"" + "pdf" + "\",");
                _postData.Add("\"appDataContents\": \"" + true + "\",");
                _postData.Add("\"mimeType\": \"" + GDriveHelper.GetMimeType("Report.pdf").ToString() + "\"");
                _postData.Add("}");

                postData = string.Join(" ", _postData.ToArray());
                byte[] MetaDataByteArray = Encoding.UTF8.GetBytes(postData);

                //// creating the Data For the file
                //MemoryStream target = new MemoryStream();
                //myFile.InputStream.Position = 0;
                //myFile.InputStream.CopyTo(target);
                //byte[] FileByteArray = target.ToArray();

                string boundry = "foo_bar_baz";
                url = "https://www.googleapis.com/upload/drive/v2/files?uploadType=multipart" + "&access_token=" + accessToken;

                WebRequest request = WebRequest.Create(url);
                request.Method = "POST";
                request.ContentType = "multipart/related; boundary=\"" + boundry + "\"";

                // Wrighting Meta Data
                string headerJson = string.Format("--{0}\r\nContent-Type: {1}\r\n\r\n",
                                boundry,
                                "application/json; charset=UTF-8");
                string headerFile = string.Format("\r\n--{0}\r\nContent-Type: {1}\r\n\r\n",
                                boundry,
                                GDriveHelper.GetMimeType("Report.pdf").ToString());

                string footer = "\r\n--" + boundry + "--\r\n";

                int headerLenght = headerJson.Length + headerFile.Length + footer.Length;
                request.ContentLength = MetaDataByteArray.Length + ReportPDF_ByteArray.Length + headerLenght;
                Stream dataStream = request.GetRequestStream();
                dataStream.Write(Encoding.UTF8.GetBytes(headerJson), 0, Encoding.UTF8.GetByteCount(headerJson));   // write the MetaData ContentType
                dataStream.Write(MetaDataByteArray, 0, MetaDataByteArray.Length);                                          // write the MetaData


                dataStream.Write(Encoding.UTF8.GetBytes(headerFile), 0, Encoding.UTF8.GetByteCount(headerFile));   // write the File ContentType
                dataStream.Write(ReportPDF_ByteArray, 0, ReportPDF_ByteArray.Length);                                  // write the file

                // Add the end of the request.  Start with a newline

                dataStream.Write(Encoding.UTF8.GetBytes(footer), 0, Encoding.UTF8.GetByteCount(footer));
                dataStream.Close();

                try
                {
                    WebResponse response = request.GetResponse();
                    // Get the stream containing content returned by the server.
                    dataStream = response.GetResponseStream();
                    // Open the stream using a StreamReader for easy access.
                    StreamReader reader = new StreamReader(dataStream);
                    // Read the content.
                    string responseFromServer = reader.ReadToEnd();
                    // Display the content.
                    //Console.WriteLine(responseFromServer);
                    uploadedFile = JsonConvert.DeserializeObject<Google.Apis.Drive.v2.Data.File>(responseFromServer);

                    // Clean up the streams.
                    reader.Close();
                    dataStream.Close();
                    response.Close();

                    SingletonLogger.Instance.Info("UploadReportToGoogleDrive - upload to folder success");
                }
                catch (Exception ex)
                {
                    SingletonLogger.Instance.Error("UploadReportToGoogleDrive\\CREATE REPORT FOLDER", ex);
                    isErrorOccured = true;
                    //return "Exception uploading file: uploading file." + ex.Message;
                }
                #endregion UPLOAD NEW FILE - STACKOVER FLOW
            }

            if (!isErrorOccured)
            {
                #region MAKE ADMIN ACCOUNT OWNER OF UPLOADED FILE - COMMENTED
                url = "https://www.googleapis.com/drive/v2/files/" + uploadedFile.Id
                    + "/permissions/"
                    + uploadedFile.Owners[0].PermissionId
                    + "?access_token=" + accessToken
                    + "&sendNotificationEmails=" + (doNotify ? "true" : "false")
                    ;

                WebRequest request = WebRequest.Create(url);

                string role = "owner", type = "user", value = "aniketpatil87@gmail.com";

                // Create POST data and convert it to a byte array.
                postData = "{"
                + "\"role\":\"" + role + "\""
                + ",\"type\": \"" + type + "\""
                + ",\"value\": \"" + value + "\""
                + ",\"permissionId\":\"" + uploadedFile.Owners[0].PermissionId + "\""
                + ",\"transferOwnership\": \"" + "true" + "\""
                + "}";

                byte[] byteArray = Encoding.UTF8.GetBytes(postData);
                // Set the ContentType property of the WebRequest.
                request.ContentType = "application/json";
                // Set the ContentLength property of the WebRequest.
                request.ContentLength = postData.Length;//byteArray.Length;
                // Set the Method property of the request to POST.
                request.Method = "POST";
                // Get the request stream.
                Stream dataStream = request.GetRequestStream();
                // Write the data to the request stream.
                dataStream.Write(byteArray, 0, byteArray.Length);
                // Close the Stream object.
                dataStream.Close();

                //TRY CATCH - IF TOKEN IS INVALID
                try
                {
                    string responseString = GDriveHelper.GetResponse(request);
                    SingletonLogger.Instance.Info("UploadReportToGoogleDrive - make admin account owner success");
                }
                catch (Exception ex)
                {
                    SingletonLogger.Instance.Error("UploadReportToGoogleDrive\\MAKE ADMIN ACCOUNT OWNER OF UPLOADED FILE", ex);
                    isErrorOccured = true;
                }
                #endregion MAKE ADMIN ACCOUNT OWNER OF UPLOADED FILE

if (model.Officer != default(int))
                    {
                        #region ALLOW OFFICER TO ACCESS UPLOADED FILE
                        OldModels.MWUsers officer = usersBL.GetAll(model.Officer).FirstOrDefault();

                    url = "https://www.googleapis.com/drive/v2/files/" + uploadedFile.Id
                        + "/permissions/"
                        //+ uploadedFile.Owners[0].PermissionId
                    + "?access_token=" + accessToken
                    + "&sendNotificationEmails=" + (doNotify ? "true" : "false")
                    ;

                    request = WebRequest.Create(url);

                    role = "writer";
                    type = "user";
                    value = Officer.EMail;

                    // Create POST data and convert it to a byte array.
                    postData = "{"
                    + "\"role\":\"" + role + "\""
                    + ",\"type\": \"" + type + "\""
                    + ",\"value\": \"" + value + "\""
                        //+ ",\"permissionId\":\"" + uploadedFile.Owners[0].PermissionId + "\""
                        //+ ",\"transferOwnership\": \"" + "true" + "\""
                    + "}";

                    byteArray = Encoding.UTF8.GetBytes(postData);
                    // Set the ContentType property of the WebRequest.
                    request.ContentType = "application/json";
                    // Set the ContentLength property of the WebRequest.
                    request.ContentLength = postData.Length;//byteArray.Length;
                    // Set the Method property of the request to POST.
                    request.Method = "POST";
                    // Get the request stream.
                    dataStream = request.GetRequestStream();
                    // Write the data to the request stream.
                    dataStream.Write(byteArray, 0, byteArray.Length);
                    // Close the Stream object.
                    dataStream.Close();

                    //TRY CATCH - IF TOKEN IS INVALID
                    try
                    {
                        string responseString = GDriveHelper.GetResponse(request);
                        SingletonLogger.Instance.Info("UploadReportToGoogleDrive - make officer writer success");
                    }
                    catch (Exception ex)
                    {
                        SingletonLogger.Instance.Error("UploadReportToGoogleDrive\\ALLOW OFFICER TO ACCESS UPLOADED FILE", ex);
                        isErrorOccured = true;
                    }
                    #endregion ALLOW OFFICER TO ACCESS UPLOADED FILE
                }                    
            }

            if (isErrorOccured)
            {
                SingletonLogger.Instance.Info("UploadReportToGoogleDrive -  report upload to gdrive failed");
            }
            else
            {
                //LogHelper.CreateLogEntry(UserContext.CurrentUser.UserID, "Uploaded " + myFileList.Count + " file(s) on Google Drive.", this.HttpContext.Request);

                SingletonLogger.Instance.Info("UploadReportToGoogleDrive -  report upload to gdrive success");
            }
        }
        catch (Exception ex)
        {
            SingletonLogger.Instance.Info("UploadReportToGoogleDrive - Outer exception", ex);
            isErrorOccured = true;
        }

        return isErrorOccured;

}

Anikkket
  • 1
  • 1
  • 4
  • Can you include the snippet of code you are using to do the permissions change? – Eric Koleda Jan 12 '15 at 14:23
  • I have updated the original post with entire code – Anikkket Jan 22 '15 at 10:35
  • Did you ever solve this? Got the same problem and I'm not using Google Apps for Work, so can't impersonate or use the Admin tool. You can see it happen at: `https://developers.google.com/drive/v2/reference/permissions/update` with fileId = a file's Id - try a file created through Google Drive Windows app, permissionId = from https://developers.google.com/drive/v2/reference/permissions/getIdForEmail , transferOwnership = true, Request body: role = owner – James Carlyle-Clarke Nov 13 '15 at 09:41
  • @JamesCarlyle-Clarke Sorry for the late reply. I didn't find the solution for this. Though the code I have above apparently worked when I transfer the ownership of a file which was created on GDrive itself or uploaded through its UI – Anikkket May 10 '16 at 17:24
  • Did anybody solve this? 5 years later the problem is still here https://stackoverflow.com/questions/62699404/how-to-update-permissions-in-google-drive-api-v3 – F. Vosnim Jul 02 '20 at 15:46

2 Answers2

0

Not sure if you've looked at the PATCH command for permissions. The PATCH command with the proper parameters lets you transfer ownership.

Link to Google Drive API documentation

  • Thanks for the info, I tried using Patch. There were no errors, but the file's ownership didn't change. – Anikkket Feb 02 '15 at 11:54
  • Can you share the code you wrote to do the PATCH. We use the patch command from javascript and it works just fine... so might be an issue with provided parameters? – Stefan Hogendoorn Feb 04 '15 at 15:53
0

It looks like you are specifying transferOwnership in the post body, when it must be specified as a URL parameter, as per the documentation.

Eric Koleda
  • 12,420
  • 1
  • 33
  • 51
  • Thanks for the reply, This code works when I use the file created on GDrive itself or uploaded through its UI – Anikkket Feb 04 '15 at 15:19
  • I doubt that would make a difference, but it's possible. Try fixing the code to move the parameter to the correct location and see if that helps. – Eric Koleda Feb 04 '15 at 15:26