I'm using Google Drive API in Python to make archiving of my files.
However i am having an issue renaming the copy of my original file.
The title of my new file defaults to
'Copy of + original filename'
However I want my new file's name is
'original filename + current date'
I can't find how to change the title configure in the copied code or rename the new file I have copied.
The copy code I used is:
service.files().copy(fileId=original_file_id).execute()
Does anyone know how to rename a file title in Python? Or any alternate method will also be welcome.
I'm unsure how exactly you want the date and the copied file name to be formatted, but you can do the following:
Retrieve the name of the original file via Files: get.
Copy the file via Files: copy, and retrieve the copied file ID.
Build the desired name, using the name of the original file and whatever date you have.
Update the copy with the new name, via Files: update.
Code snippet:
from datetime import date
def copyFile(service, fileId):
fileName = service.files().get(fileId=fileId).execute()["name"]
copyId = service.files().copy(fileId=fileId).execute()["id"]
currentDate = date.today()
copyName = "{} | {}".format(fileName, currentDate)
body = { "name": copyName }
service.files().update(fileId=copyId, body=body).execute()
Please note i am not a python developer this code is a wild guess on my part you will need to fix it.
The Files.copy has a parameter called name which you can send with the request. I am not sure how the optional parameters are sent with the python libray. The only issue i see with this is that you will need to do a file.get first so that you have the current name of the file that you can use to pass to this method.
request = service.files().copy(fileId=original_file_id);
request.Name = 'original file name + current date';
response = request.execute();
Related
I am a python developer and somewhat new to using Google's gMail API to import .eml files into a gMail account.
I've gotten all of the groundwork done getting my oAuth credentials working, etc.
However, I am stuck where I load in the data-file. I need help loading the message data in to place in a variable..
How do I create the message_data variable reference - in the appropriate format - from my sample email file (which is stored in rfc822 format) that is on disk?
Assuming I have a file on disk at /path/to/file/sample.eml ... how do I load that to message_data in the proper format for the gMail API import call?
...
# how do I properly load message_data from the rfc822 disk file?
media = MediaIoBaseUpload(message_data, mimetype='message/rfc822')
message_response = service.users().messages().import_(
userId='me',
fields='id',
neverMarkSpam=True,
processForCalendar=False,
internalDateSource='dateHeader',
media_body=media).execute(num_retries=2)
...
You want to import an eml file using Gmail API.
You have already been able to get and put values for Gmail API.
You want to achieve this using google-api-python-client.
service in your script can be used for uploading the eml file.
If my understanding is correct, how about this answer? Please think of this as just one of several possible answers.
Modification point:
In this case, the method of "Users.messages: insert" is used.
Modified script:
Before you run the script, please set the filename with the path of the eml file.
eml_file = "###" # Please set the filename with the path of the eml file.
user_id = "me"
f = open(eml_file, "r", encoding="utf-8")
eml = f.read()
f.close()
message_data = io.BytesIO(eml.encode('utf-8'))
media = MediaIoBaseUpload(message_data, mimetype='message/rfc822', resumable=True)
metadata = {'labelIds': ['INBOX']}
res = service.users().messages().insert(userId=user_id, body=metadata, media_body=media).execute()
print(res)
In above script, the following modules are also required.
import io
from googleapiclient.http import MediaIoBaseUpload
Note:
In above modified script, {'labelIds': ['INBOX']} is used as the metadata. In this case, the imported eml file can be seen at INBOX of Gmail. If you want to change this, please modify this.
Reference:
Users.messages: insert
If I misunderstood your question and this was not the result you want, I apologize.
I have been trying to move file from one folder to another in my google drive using PyDrive
file2 = drive.CreateFile({'id': <file id>})
file2['parents']=<destination folder id>
file2.Upload()
Is it possible to change folders like this? If not please suggest any alternatives using PyDrive.
It's been a while since this question was asked, but for those that happen upon this, here's what worked for me. The solutions above didn't work for me, but what did was that I changed 'kind': 'drive#fileLink' to 'drive#parentReference'.
Final code looks like;
file2 = drive.CreateFile({'id': <file id>})
file2['parents'] = [{"kind": "drive#parentReference", "id": <destination_id>}]
file2.Upload()
This will overwrite the parent info for the file, effectively emulating the 'Move To' function in the Drive UI.
PyDrive is a convenient wrapper for the Google Drive api, however it seems there are still some methods that don't work as expected.
Fortunately you can still access the underlying google drive api methods proposed here like so:
file_id = <file id>
new_parent = <new parent id>
files = drive.auth.service.files()
file = files.get(fileId= file_id, fields= 'parents').execute()
prev_parents = ','.join(p['id'] for p in file.get('parents'))
file = files.update( fileId = file_id,
addParents = new_parent,
removeParents = prev_parents,
fields = 'id, parents',
).execute()
I just tested this, and if you're using the web UI, you will need to refresh the pages to see changes.
Note that a single file can have multiple parents, which can be pretty useful for things like jQuery galleries.
The parents array contains not just the IDs of each parent folder but an object with additional information.
Thus, you need to change the line:
file2['parents'] += ['<parent ID>']
to:
file2['parents'].append({"kind": "drive#fileLink", "id": '<parent ID>'})
The complete example would therefore be:
file2 = drive.CreateFile({'id': <file id>})
file2['parents'].append({"kind": "drive#fileLink", "id": '<parent ID>'})
file2.Upload()
You can find an example of using folders here.
what actually worked :-
file1 = drive.CreateFile({'id': id_[0]})
file1.Upload()
file1['parents'] = [{"kind": "drive#parentReference", "id": "destination_folder_id"}]
file1.Upload()
Explanation:-
line 1:-
file1 = drive.CreateFile({'id': 'file_id_here'}) #Create's GoogleDriveFile instance
the above line of code doesn't imports the meta data from your file in order to do that we use:-
line 2:-
file1.Upload() #gets metadata of the file
and once meta data is retrived we change the parent folder id to the destination folder id in line 3
line 3:-
file1['parents'] = [{"kind": "drive#parentReference", "id": "destination_folder_id"}]
now upload it once again to save the changes (line 4),
line 4:-
file1.Upload()# save and update changes
Here's the link to github repo with the working code.
In my opinion it should be very easy, but because of some reason I can't find the right way how to do it: how should I update a file in Google Drive using Python?
My code:
from pydrive.auth import GoogleAuth
from pydrive.drive import GoogleDrive
gauth = GoogleAuth()
gauth.LoadCredentialsFile("mycreds.txt")
drive = GoogleDrive(gauth)
file = drive.CreateFile({'title': 'Hello.txt'})
file.SetContentString('test 1')
file.Upload()
This creates a new file. Now I want to add to this file next line 'test 2'.
Running above code each time creates new file, which is not what I want.
Can anyone help me with this please?
Daddy
This is because you call CreateFile every time you run the script and therefore creating a new document.
If you'd want to update the file without closing the script:
file = drive.CreateFile({'title':'appdata.json', 'mimeType':'application/json'})
file.SetContentString('{"firstname": "John", "lastname": "Smith"}')
file.Upload() # Upload file
file.SetContentString('{"firstname": "Claudio", "lastname": "Afshar"}')
file.Upload() # Update content of the file
I haven't found a way to get a GoogleDriveFile instance by ID, but the documentation mentions iterating over all files that match a description:
file_list = drive.ListFile({'q': "'root' in parents and trashed=false"}).GetList()
for file in file_list:
print 'title: %s, id: %s' % (file['title'], file['id'])
So if you use this by searching for your file and checking if the list contains only one item, you'd have found your specific document.
For search parameters of 'q': https://developers.google.com/drive/web/search-parameters.
file_list = drive.ListFile({'q': "title='hello.doc' and trashed=false"}).GetList()
if len(file_list) == 1:
file = file_list.next()
updated_content = file.GetContentString() + "New content"
file.SetContentString(updated_content)
file.Upload()
Sorry I don't know more details, if this doesn't work for you maybe look at the official python Google API: https://developers.google.com/drive/web/quickstart/python
First of all, each time you use drive.CreateFile() and file.Upload(), it will create a new instance. To overwrite on the same file, you have to specify the file id of that file.
For example, you may create a new file like this:
yourfile_id = '*****'
file = drive.CreateFile({'title': 'Hello.txt', 'id': yourfile_id})
This way, you will make sure that you would not have a duplication of the file.
Second, to update your file, you have to read it and append what you want to add to the read data.
Below, show an example:
file_list = drive.ListFile({'q': "'root' in parents and trashed=false"}).GetList()
for file in file_list:
if file['title'] == 'Hello.txt':
new_file = drive.CreateFile({'title': file['title'], 'id': file['id']})
file_content = new_file.GetContentString()
file_content = file_content + '\ntest 2'
new_file.SetContentString(file_content)
new_file.Upload()
the first line gets a list of all files in the root (you can search in any subfolders by replacing the 'root' with the folder id)
The for loop finds the file you want ('Hello.txt') and feed the new_file with its title and id (to replace with the old one, as the piece of code mentioned before)
Next two lines read the file content and append new data and the last two lines upload and update the file.
Flask-uploads has something called UploadSet which is described as a "single collection of files". I can use this upload set to save my file to a predefined location. I've defined my setup:
app = Flask(__name__)
app.config['UPLOADS_DEFAULT_DEST'] = os.path.realpath('.') + '/uploads'
app.config['UPLOADED_PHOTOS_ALLOW'] = set(['png', 'jpg', 'jpeg'])
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
# setup flask-uploads
photos = UploadSet('photos')
configure_uploads(app, photos)
#app.route('/doit', method=["POST"])
def doit():
myfile = request.files['file']
photos.save(myfile, 'subfolder_test', 'filename_test')
return ''' blah '''
This should save to ./uploads/photos/subfolder_test/filename_test.png
My test image is: 2.6MB and is a png file. When I upload this file, I get the error:
...
File "/home/btw/flask/app.py", line 57, in doit
photos.save(myfile, 'subfolder_test', 'filename_test')
File "/usr/local/lib/python2.7/dist-packages/flaskext/uploads.py", line 388, in save
raise UploadNotAllowed()
UploadNotAllowed
However it doesn't say exactly what is not allowed. I have also tried removing all constraints, but the app still throws this error. Why?
EDIT:
Okay, so I figured out that it's not actually the constraints that is causing the problem. It is the subfolder and/or the filename that is causing the problem:
# This works
# saves to: ./uploads/photos/filename_test.png
photos.save(myfile)
But I want to save to my custom location ./uploads/photos/<custom_subdir>/<custom_filename>. What is the correct way of doing this?
You need to give your filename_test the extension as well
photos.save(myfile, 'subfolder_test', 'filename_test.png')
The UploadSet checks the extension on the new file name and will throw the exception if the new extension is not allowed.
Since you are not giving the new file an extension, it does not recognize it.
You can add a dot to file's name, then the file's extension will be appended.
photos.save(myfile, 'subfolder_test', 'filename_test' + '.')
save(storage, folder=None, name=None)
Parameters:
storage – The uploaded file to save.
folder – The subfolder within the upload set to save to.
name – The name to save the file as. If it ends with a dot, the file’s extension will be appended to the end.
The link to the code is here (didn´t copy it here to give the guy credit):
I don´t want it to change the name with the date as is currently doing, but to download the file "finviz.csv" and rewrite it each day (with the scheduler task) to keep the data updated in my data system.
I´ve tried some tweaks, but I´m no developer I don´t have a clue how to do it.
Can you please help?
The comments in the code described it quite clearly:
# we're going to name the file by the date it was downloaded (e.g. 2012-3-18.csv)
fname = now.strftime("%Y-%m-%d")+".csv";
So just change the line to
fname = "finviz.csv";
And fix the file existence check logic:
# check if the file does not already exist
if not os.path.isfile(savepath+"/"+fname):
# open a file to save the data to ("wb" means write binary mode)
outfile = open(savepath+"/"+fname, "wb");
# download the data from the url specified above
infile = urllib2.urlopen(url);
# read the downloaded data and write it to our output file
outfile.write(infile.read());
# close the output file once we're done
outfile.close();
else:
print "'"+fname+"' ALREADY EXISTS in the save directory '"+savepath+"'.";
to:
# open a file to save the data to ("wb" means write binary mode)
outfile = open(savepath+"/"+fname, "wb");
# download the data from the url specified above
infile = urllib2.urlopen(url);
# read the downloaded data and write it to our output file
outfile.write(infile.read());
# close the output file once we're done
outfile.close();
You have to change the line
fname = now.strftime("%Y-%m-%d")+".csv";
for
fname = "finviz.csv";
And you also need to delete this if (and its corresponding else):
if not os.path.isfile(savepath+"/"+fname):