Closed matiasrebori closed 2 years ago
Hey, yes service account - see example here https://github.com/iterative/PyDrive2/issues/21 or https://docs.iterative.ai/PyDrive2/pydrive2/#pydrive2.auth.GoogleAuth.LocalWebserverAuth . Please give one of those a try and let us know if something doesn't work.
Also, see how fsspec
- https://github.com/iterative/PyDrive2/blob/main/pydrive2/fs/spec.py#L132
Thanks you for your help, the example you provided is working. One last question i have a function to upload files like this
def upload_file(filepath, filename, id_drive_folder=DRIVE_FOLDER):
"""
upload a file to desired folder.
:param filepath: ubicacion del archivo
:param filename: nombre del archivo
:param id_drive_folder: id de la carpeta del drive
:return:
"""
gdrive = login()
metadata = {
'parents': [
{"kind": "drive#fileLink", "id": id_drive_folder}
],
'title': f'{filename}'
}
# create file
archivo = gdrive.CreateFile(metadata=metadata)
# set the content of the file
archivo.SetContentFile(filepath)
# upload the file to google drive
archivo.Upload()
this creates a new instance of GoogleDrive() for every call when doing gdrive = login()
, is this approach good or is better to have only one instance of GoogleDrive() authenticated when the application starts i.g. instanciate only one time gdrive = login()
and use this instance to all the consequent calls
@shcheklein im trying to upload a base64 image stored in memory, but SetContentFile doesnt accepts io.BytesIO(). Exists a way to uploads files with io.BytesIO?
is this approach good or is better to have only one instance of GoogleDrive() authenticated when the application starts i.g. instanciate only one time gdrive = login() and use this instance to all the consequent calls
One instance should be enough. You don't need to do the whole workflow every time (it'll be cached, but anyway you don't need this)
im trying to upload a base64 image stored in memory, but SetContentFile doesnt accepts io.BytesIO(). Exists a way to uploads files with io.BytesIO?
yes, you could do SetContentString
, or you could do even something like:
file.content = io.BytesIO(...)
files.Upload()
im trying to upload a base64 image stored in memory, but SetContentFile doesnt accepts io.BytesIO(). Exists a way to uploads files with io.BytesIO?
yes, you could do
SetContentString
, or you could do even something like:file.content = io.BytesIO(...) files.Upload()
thanks for your help. I couldn't make it work with SetContentString()
. It worked with the second recommendation.
a function receives the param bytes_file
# create file
archivo = gdrive.CreateFile(metadata=metadata)
# set the content of the file
archivo.content = bytes_file
# upload the file to google drive
archivo.Upload()
then to execute
import base64
import io
file = open(r'C:\Users\xxx\Downloads\base64.txt', 'r')
# read base64 string
base64_string: str = file.read()
# decode to data bytes
image_bytes: bytes = base64.b64decode(base64_string)
# Buffered I/O implementation using an in-memory bytes buffer.
image_file = io.BytesIO(image_bytes)
# upload file
# file, filename, mimetype
upload_media(image_bytes, 'test2_4', 'image/jpeg')
@shcheklein if you want i can contribute to the docs with how to authenticate with a Service Account and how to upload media. Also i think SetContentFile can easily support io.BytesIO(), or we could do another method like SetMediaFile() or something like this.
@matiasrebori that would very helpful, thanks.
Also i think SetContentFile can easily support io.BytesIO(),
I'm not sure about this tbh. It's quite explicit and does one thing. SetContentString
or we may introduce another wrapper SetContentStream
or something. But also, I think it's fine that you could do self.content =
- for now. We can document it also.
Ok, I'm not advanced on GitHub, should I open a new issue to link later with a PR?
Creating a PR if fine an enough!
is this approach good or is better to have only one instance of GoogleDrive() authenticated when the application starts i.g. instanciate only one time gdrive = login() and use this instance to all the consequent calls
One instance should be enough. You don't need to do the whole workflow every time (it'll be cached, but anyway you don't need this)
Hi, do you know if the low level API googleapiclient
also caches or is this a feature of pyDrive ?`
Another question, i made a function to get a specific file by name and mimetype
archivo = gdrive.ListFile(query).GetList()
query = {'q': f"title = '{filename}' and mimeType='{mimetype}'"}
the name
param in q search files using the low level API v3 works but it doesn't in pyDrive HttpError 400 Invalid query
idk if this is wrong or right, instead I find that the param title
worked with pyDrive as exact replacement for name
.
When i have a little more time i'll work in the PR :)
Hi, do you know if the low level API googleapiclient also caches or is this a feature of pyDrive ?`
I don't think googleapiclient
has any mechanism to cache credentials, refresh tokens, etc.
My point was that, even if you do multiple instances it should be also fine if you use some default settings since PyDrive will create a files with credentials that it'll try to reuse next time.
Hi, is there a way to authenticate to Drive without using the LocalWebserverAuth() method, because it promps a login page from the browser and i dont want this behaviour. I have a flask application and one feature is to save images to a specific google drive folder (uses a single organization account), this runs in a linux vm. i have a
client_secrets.json
file, this is the JSON downloaded from Google Developers Console, also i set thesettings.yaml
file to create acredentials.json
file to automate the consequents authentications. The problem is i dont want to manually login for the first time if there isnt acredentials.json
file. Im using the next piece of code to login to google driveI have a code to get data from Google Sheets and only uses the JSON file from Google Developers Console, in this code i named this file
credentials.json
. So i think theres probably a similiar way to authenticate to Google Drive.