this is shareable link link to file
id = 1wzCjl51u131v1KBgpbiKLJs8DPPakhXCFosfYjp7BY0
so manage downloads documentation.
file_id = '11wzCjl51u131v1KBgpbiKLJs8DPPakhXCFosfYjp7BY0'
request = drive_service.files().export_media(fileId=file_id,
mimeType='application/pdf')
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print ("Download %d%%." % int(status.progress() * 100))
i saved the file as dd.py, run using f5 and got this error
line 2, in
request = drive_service.files().export_media(fileId=file_id,
NameError: name 'drive_service' is not defined
First off you cant be sure that the id you find in the shareable link is in fact the id of the file on google drive this is not always the case. Actually I have never known this to be the case
drive_service' is not defined
Second you need create the drive service and be authenticated before you can run that code. You should try following the python quickstart
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# If modifying these scopes, delete the file token.json.
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('drive', 'v3', http=creds.authorize(Http()))
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1})'.format(item['name'], item['id']))
if __name__ == '__main__':
main()
Related
I just start learning the python scripting and I created a script using pydrive and the function is uploading all files from local folder (linux OS) to google drive but I'm planning to modify the script for my automation and add the function that can upload only the most recent file added to the local folder with no reuploading of all the files inside the folder, may I know if this is possible with python script alone?
Thank you in advance!
You dont need to use pydrive. You can use the Google api python client library directly. As far as i know pydrive does use the client library internally. There's a starter example here
Quick start python
from __future__ import print_function
import os.path
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
from googleapiclient.discovery import build
from googleapiclient.errors import HttpError
# If modifying these scopes, delete the file token.json.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
def main():
"""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.json 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.json'):
creds = Credentials.from_authorized_user_file('token.json', SCOPES)
# 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(
'credentials.json', SCOPES)
creds = flow.run_local_server(port=0)
# Save the credentials for the next run
with open('token.json', 'w') as token:
token.write(creds.to_json())
try:
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
return
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
except HttpError as error:
# TODO(developer) - Handle errors from drive API.
print(f'An error occurred: {error}')
if __name__ == '__main__':
main()
Manage uploads
file_metadata = {'name': 'photo.jpg'}
media = MediaFileUpload('files/photo.jpg', mimetype='image/jpeg')
file = drive_service.files().create(body=file_metadata,
media_body=media,
fields='id').execute()
print 'File ID: %s' % file.get('id')
I can get mydrive folders, but I can't access shared drive folders from Google Drive API.
This is my code.(almost same to the Guides' code here)
I followed the Guides, finished "Enable the Drive API", execute the pip command on VScode, and put credentials.json to the working directory.
(I got no error, only got filename list of mydrive or 'No files found' that is printed by the code.)
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
def main():
"""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(
'credentials.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)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
if __name__ == '__main__':
main()
Notice that the API has the includeItemsFromAllDrives parameter in order to determine whether shared drive items show up or not in the results.
The Python API V3 wrapper also has this parameter included on it's list method implementation that needs to be included when calling the list() method:
...
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, includeItemsFromAllDrives=True, supportsAllDrives=True, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
...
I am trying to upload a file to Google Drive using its Python API since I need to make a script to upload automatic backup copies from my server to Google Drive if user interaction. I have the following code which I have extracted from the Google Drive documentation.
Code of my Script:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from apiclient.http import MediaFileUpload
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
def main():
"""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(
'credentials.json', SCOPES)
creds = flow.run_local_server()
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
file_metadata = {
'name' : 'report.csv',
'mimeType' : 'application/vnd.google-apps.spreadsheet'
}
media = MediaFileUpload('files/report.csv',
mimetype='text/csv',
resumable=True)
file = drive_service.files().create(body=file_metadata,
media_body=media,
fields='id').execute()
print ("File ID: %s" % file.get("id"))
main()
The errors that it shows me are these:
Traceback (most recent call last):
File "gdriveprueba.py", line 55, in <module>
resumable=True)
File "/home/servicioweb/.local/lib/python2.7/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
return wrapped(*args, **kwargs)
File "/home/servicioweb/.local/lib/python2.7/site-packages/googleapiclient/http.py", line 554, in __init__
fd = open(self._filename, 'rb')
IOError: [Errno 2] No such file or directory: 'files/report.csv'
the files directory create it manually in Google Drive but it keeps telling me that it can not find it, what could be happening that I can not see? I have 2 days in this and I have not been able to upload the files from the script.
You are confusing the parameters on line 50 and line 53. The parameter name which goes in the file_metadata structure is referring to the name of the file on the google drive. The first parameter to the MediaFileUpload constructor refers to the path on the local drive. For your code to work this file needs to exist. Also you are referring to an undefined variable drive_service on line 56. You can either redefine the variable service, which is defined in the main function, as a global variable, or move the code which requests the api upload (starting on line 49) into the function main. Also main needs to be called first before your upload code to actually create the service object.
If you just want to upload this to the root of your drive, you can just create the file files/report.csv, relative to this file, and you will have the file report.csv created on the root of your drive.
To create the file files/report.csv, you need to find the fileId of the directory files on your google drive, and send that as a parameter to the create api call.
To find the fileId run this code:
dirp = "files" # Name of directory to find.
parent_id = "" # The id we are looking for.
query = ("name='%s'" % (dirp))
resp = service.files().list(
q=query,
fields="files(id, name)",
pageToken=None).execute()
files = resp.get('files', [])
if len(files) > 0:
parent_id = files[0].get('id')
Now use the variable parent_id in the api request to create the file.
media = MediaFileUpload('report.csv',
mimetype='text/csv',
resumable=True)
meta_data= { 'name': 'report.csv',
'mimeType' : 'application/vnd.google-apps.spreadsheet',
'parents': [parent_id] }
f = service.files().create(
body=meta_data,
media_body=media,
fields='id').execute()
if not f is None: print("[*] uploaded %s" % (f.get('id')))
Here is more info on the parameters for the create function.
The working code would look like this:
from __future__ import print_function
import pickle
import os.path
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
from apiclient.http import MediaFileUpload
# If modifying these scopes, delete the file token.pickle.
SCOPES = ['https://www.googleapis.com/auth/drive.metadata.readonly']
service = None
def main():
"""Shows basic usage of the Drive v3 API.
Prints the names and ids of the first 10 files the user has access to.
"""
global service
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(
'credentials.json', SCOPES)
creds = flow.run_local_server()
# Save the credentials for the next run
with open('token.pickle', 'wb') as token:
pickle.dump(creds, token)
service = build('drive', 'v3', credentials=creds)
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print(u'{0} ({1})'.format(item['name'], item['id']))
main()
# Retrieve the parent ID of the files/ directory
dirp = "files" # Name of directory to find.
parent_id = "" # The id we are looking for.
query = ("name='%s'" % (dirp))
resp = service.files().list(
q=query,
fields="files(id, name)",
pageToken=None).execute()
files = resp.get('files', [])
# Create a file object for file 'report.csv' on your local drive.
media = MediaFileUpload('report.csv',
mimetype='text/csv',
resumable=True)
# Upload the file.
if len(files) > 0:
parent_id = files[0].get('id')
meta_data= { 'name': 'report.csv',
'parents': [parent_id],
'mimeType' : 'application/vnd.google-apps.spreadsheet' }
f = service.files().create(
body=meta_data,
media_body=media,
fields='id').execute()
if not f is None: print("[*] uploaded %s" % (f.get('id')))
else: print("The folder files/ does not exist on your drive.")
I am trying to download/export a file according to the v3 example published by google. I am getting the "Daily Limit for Unauthenticated Use Exceeded. Continued use requires signup." error.
I have searched here and elsewhere and all of the links suggest I am missing setting up the credentials. However, I am building on top of the basic quickstart example and am able to list out the contents of my drive folder in this same application. And yes, I have changed the requested scope from drive.metadata.readonly to drive.readonly to support downloading. What am I missing?
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
import io
from googleapiclient.http import MediaIoBaseDownload
# Setup the Drive v3 API
SCOPES = 'https://www.googleapis.com/auth/drive.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
drive_service = build('drive', 'v3', http=creds.authorize(Http()))
# Call the Drive v3 API to list first 10 items (this works)
# example from google.
results = drive_service.files().list(
pageSize=10, fields="nextPageToken, files(id, name)").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1})'.format(item['name'], item['id']))
# Try to download the first item (it's a google doc I can edit, this FAILS)
# code pretty much lifted from google
file_id = items[0]['id']
print (file_id)
request = drive_service.files().export_media(fileId=file_id,
mimeType='application/pdf')
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print ( "Download %d%%." % int(status.progress() * 100) )
Found it. The example from Google was caching the credentials file (credentials.json). When I originally ran the example the scoped permissions were not for drive.readonly, but for drive.metadata.readonly. I think when I changed them the request was not longer valid.
I deleted and credentials.json and re-ran the script (and re-approved the credentials request on my browser) and it was successful. I also ended up using the following to store the data as the BytesIO wasn't actually writing to disk.
data = drive_service.files().export(fileId=file_id,
mimeType='application/pdf').execute()
f = open('MyFile.pdf','wb')
f.write(data)
f.close()
in this code :
file_id = '0BwwA4oUTeiV1UVNwOHItT0xfa2M'
request = drive_service.files().get_media(fileId=file_id)
fh = io.BytesIO()
downloader = MediaIoBaseDownload(fh, request)
done = False
while done is False:
status, done = downloader.next_chunk()
print "Download %d%%." % int(status.progress() * 100)
I don't know how to get file_id , I was getting file_id while uploading but now I am not able to figure out how to get file_id of the file which is present on Google Drive.
Ex. if my uploaded file has name A001002.pdf , how can i get file id for this file.
there is some reference online which i am not able to understand.
link: files.list
any help?
The file.list method contains a q paramater which is used for searching
GET https://www.googleapis.com/drive/v3/files?q=name+%3D+'hello'&key={YOUR_API_KEY}
Python Guess
"""
Shows basic usage of the Drive v3 API.
Creates a Drive v3 API service and prints the names and ids of the last 10 files
the user has access to.
"""
from __future__ import print_function
from apiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# Setup the Drive v3 API
SCOPES = 'https://www.googleapis.com/auth/drive.metadata.readonly'
store = file.Storage('credentials.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets('client_secret.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('drive', 'v3', http=creds.authorize(Http()))
# Call the Drive v3 API
results = service.files().list(
pageSize=10, fields="*").execute()
items = results.get('files', [])
if not items:
print('No files found.')
else:
print('Files:')
for item in items:
print('{0} ({1})'.format(item['name'], item['id']))
Note this example does not show how to add the additional parameter i am still Googling that but i am not a python dev you may know more about how to do that than me.
Depending on your implementation, there is one more alternative. In case you do not need to programmatically get the fileID you can just open the file in google docs from the browser and the ID is shown in the URL.