I used to move my files into a dropbox enabled folder and let them deal with the uploading but that feature has become so unreliable to be uesless to me. Instead I've written this python3 script to upload files using the dropbox sdk instead.
Downloading the dropbox python sdk is as easy as:
pip install dropbox
If your file is less than 150MB then dropbox.files_upload can be used, larger than that and dropbox.files_upload_session_start must be called and given a small chunk of your file, with the remaining chunks being uploaded with dropbox.files_upload_session_append and the final chunk with dropbox.files_upload_session_finish.
What a faff! So this script will do it all for you and print out a nice progress bar too :)
This has been sped up a lot |
Call with upload_to_dropbox(file_path, target_path) where file_path is the file you want to upload and target_path is the dropbox location (including the uploaded file name).
It will also return a True value if the upload was successful.
I work out the dropbox location by finding the folder I want in a browser and getting the url
e.g. "https://www.dropbox.com/home/Projects/Groobles%20Files"
Then remove the dropbox.com/home bit and replace %20s with the spaces they represent, then add the file name
e.g. "/Projects/Groobles Files/uploadedfile.zip"
The script:
import math
import dropbox
## Token required to access dropbox
ACCESS_TOKEN="ABCDEFGHIJKLMNOP1234567890SECRETTOKEN0000"
class UploadProgressBar:
def __init__(self, file_size, bar_length=20):
self.file_size = file_size
self.bar_length = bar_length
self.progress = 0
guide_bar_string=" "
for _ in range(bar_length):
guide_bar_string+="_"
print(guide_bar_string)
print("|", end="")#start of progress bar
def updateProgress(self, uploaded_data):
"""! Update the bars progress level.
@param uploaded_data int - The amount of data uploaded, this will be compared to the self.file_size. (Using file.tell() can be used to collect this information)
@note Printing anything before the progress bar is finished will ruin the look of the progress bar design
"""
percentage = (uploaded_data / self.file_size) * self.bar_length
new_progress = math.floor(percentage)
if (new_progress > self.progress):
newbars=""
for _ in range(new_progress - self.progress):
newbars += "#"
self.progress = new_progress
if (self.progress == self.bar_length):
print(newbars + "|")#end of the progress bar
else:
print(newbars, end="", flush=True)
def upload_file(file_path,target_path):
dbx = dropbox.Dropbox(ACCESS_TOKEN, timeout=900)
with open(file_path, "rb") as f:
file_size = os.path.getsize(file_path)
chunk_size = 4 * 1024 * 1024
if file_size <= chunk_size:
print("File is smaller than 150MB, uploading to dropbox using the small file method...")
try:
result = dbx.files_upload(f.read(), target_path, mode=dropbox.files.WriteMode.overwrite)
except dropbox.exceptions.ApiError as err:
print("\nError:", err)
return False
else:
print(result.name , "uploaded successfully to ", result.path_display)
return True
else:
print("File is larger than 150MB, uploading to dropbox using large file method...")
try:
print("Starting upload session...")
progbar = UploadProgressBar(os.path.getsize(file_path), 20);
progbar.updateProgress(0);
upload_session_start_result = dbx.files_upload_session_start(f.read(chunk_size))
cursor = dropbox.files.UploadSessionCursor(session_id=upload_session_start_result.session_id,offset=f.tell())
commit = dropbox.files.CommitInfo(path=target_path, mode=dropbox.files.WriteMode.overwrite)
while f.tell() < file_size:
if (file_size - f.tell()) <= chunk_size:
result = dbx.files_upload_session_finish(f.read(chunk_size), cursor, commit)
progbar.updateProgress(os.path.getsize(file_path))
else:
progbar.updateProgress(f.tell())
dbx.files_upload_session_append(f.read(chunk_size), cursor.session_id, cursor.offset)
cursor.offset = f.tell()
except dropbox.exceptions.ApiError as err:
print("\nError:", err)
return False
else:
print(result.name , "uploaded successfully to", result.path_display)
return True
return False #we shouldn't reach here but we might if there's an issue on dropbox's end