Reputation: 97
I need to update / replace a file in my google drive through a python script, but I keep getting permissions errors. How do I fix this? Also, what is the newRevision argument for the .update() method, and how would I use that?
Code:
os.chdir(os.path.dirname(os.path.realpath(__file__))) #Fix directory
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive']
# ...
def update_file(service, file_id, new_title, new_description, new_mime_type,
new_filename, new_revision):
"""Update an existing file's metadata and content.
Args:
service: Drive API service instance.
file_id: ID of the file to update.
new_title: New title for the file.
new_description: New description for the file.
new_mime_type: New MIME type for the file.
new_filename: Filename of the new content to upload.
new_revision: Whether or not to create a new revision for this file.
Returns:
Updated file metadata if successful, None otherwise.
"""
try:
# First retrieve the file from the API.
file = service.files().get(fileId=file_id).execute()
# File's new metadata.
file['title'] = new_title
file['description'] = new_description
file['mimeType'] = new_mime_type
# File's new content.
media_body = MediaFileUpload(
new_filename, mimetype=new_mime_type, resumable=True)
# Send the request to the API.
updated_file = service.files().update(
fileId=file_id,
body=file,
media_body=media_body).execute()
return updated_file
except Exception as e:
print ('An error occurred: %s' % e)
return None
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
creds = None
# The file token.pickle stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
if os.path.exists('token.pickle'):
with open('token.pickle', 'rb') as token:
creds = pickle.load(token)
# If there are no (valid) credentials available, let the user log in.
if not creds or not creds.valid:
if creds and creds.expired and creds.refresh_token:
creds.refresh(Request())
else:
flow = InstalledAppFlow.from_client_secrets_file(
'client_secrets.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
update_file(service, '1dBOHritZIwDPECqDXXBm8BR92uF1eI99', 'Updated' , 'updated text file' , "text/plain",
'test.txt', 'false')
Error:
An error occurred: <HttpError 403 when requesting https://www.googleapis.com/upload/drive/v3/files /1dBOHritZIwDPECqDXXBm8BR92uF1eI99?alt=json&uploadType=resumable returned "The resource body includes fields which are not directly writable."
Upvotes: 0
Views: 787
Reputation: 2998
You are passing too many values in the body
parameter.
If you look at the documentation for the PATCH
upload endpoint, the body
parameter should contain only the metadata information you want to update.
In this case you are passing all the file dict
to the body parameter and this will result in an error since not every field is writable.
Try instead something like this:
def update_file(service, file_id, new_title, new_description, new_mime_type,
new_filename, new_revision):
"""Update an existing file's metadata and content.
Args:
service: Drive API service instance.
file_id: ID of the file to update.
new_title: New title for the file.
new_description: New description for the file.
new_mime_type: New MIME type for the file.
new_filename: Filename of the new content to upload.
new_revision: Whether or not to create a new revision for this file.
Returns:
Updated file metadata if successful, None otherwise.
"""
try:
# File metadata
file_metadata = {
'name': new_title,
'description': new_description
}
# File's new content.
media_body = MediaFileUpload(
new_filename, mimetype=new_mime_type) # In this case the file is small so no resumable flag needed
# Send the request to the API.
updated_file = service.files().update(
fileId=file_id,
body=file_metadata,
media_body=media_body).execute()
return updated_file
except Exception as e:
print ('An error occurred: %s' % e)
return None
About the new_revision
parameter I can't find it in the documentation. I can see the keepRevisionForever
flag which controls this behavior:
Whether to set the 'keepForever' field in the new head revision. This is only applicable to files with binary content in Google Drive. Only 200 revisions for the file can be kept forever. If the limit is reached, try deleting pinned revisions.
Upvotes: 1