Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles / Languages / Python

API Created in Flask

5.00/5 (1 vote)
1 Feb 2019CPOL2 min read 6.7K   49  
Created an API for my DropBox file uploader using Flask

Introduction

An API built in Flask which uploads files to DropBox.

Background

Image 1

  1. The user selects the files from the form.
  2. The files are sent in the request body to the Flask server.
  3. The API uploads the files to DropBox.

Note

  • The API can upload into one shot and multi-part as well.
  • The API can be tested with the Postman client as well.

Technologies Used

  • Flask: Version 1.0.2
  • Jinja: Version 2.10
  • DropBox API: Version 9.3.0
  • Python: Version 3.6.5

Prerequisites

  • Make a DropBox developers' account to get the access token for the DropBox API.
  • Paste the access token in the config.py file 

Setting Up

  • Requirements.txt: It already has all the dependencies needed to run the server.
    Python
    $ pip3 install -r requirements.txt
    
  • To run:
    Python
    $ python3 app.py
    

Code Overview

In the initialization block, I'm importing all the required modules and packages, creating a DropBox object, which requires an access token as the argument, and defining the chunk sizes. 

After that, we create a Flask instance ( __name__ is the name of the current Python module. The app needs to know where it's located to set up some paths).

I created a simple form to test my API and set its route to the homepage.

The source code is as follows:

Python
from flask import Flask, request, render_template
import dropbox
import config
import os

dbx = dropbox.Dropbox(config.exports['token'])

chunk_size = config.exports['chunkSize'] * 1024 * 1024
max_chunk = config.exports['maxChunk'] * 1024 * 1024

app = Flask(__name__)

# Made a simple form from where I send the files and test if my API is working
@app.route('/')
def index():
    return render_template('upload.html')

When the POST request is made, flask checks the files in the request.

It reads the file from start to finish in the file.seek()Then it calculates the file size and stores it in the fileSize variable.

After that, it sets the file pointer back to the start so that the file can be read again.

The logic compares the file size with the max_chunk and one shot uploads if it's <= max_chunk.

If the file size exceeds the max_chunk, then an upload session is created which basically reads chunks of 1 MB and sends the chunks to DropBox. Finally, it checks the file to see if it has reached the final chunk and finishes the session, otherwise it keeps on sending chunks to DropBox until the file comes to an end (Multi-part upload).

Note

  • DropBox can one shot upload if the file size is <= 150 MB.
  • Otherwise, it multi-part uploads.
  • The max_chunk and chunk_size variables can be altered in the config.py file.

The source code is as follows:

Python
@app.route('/upload', methods=['POST'])
def uploader():
    files = request.files.getlist('file')
    for file in files:
        try:
            filename = file.filename
            destination_path = os.path.join(config.exports['targetFolder'], filename)
            file.seek(0, 2)# reading the file from start to finish
            fileSize = file.tell()
            file.seek(0)# setting file pointer to the start of the file
            if fileSize <= max_chunk:
                dbx.files_upload(file.read(), destination_path)
            else:
                upload_session_start_result = dbx.files_upload_session_start(file.read(chunk_size))
                cursor = dropbox.files.UploadSessionCursor
                                        (session_id=upload_session_start_result.session_id,
                                                           offset=file.tell())
                commit = dropbox.files.CommitInfo(path=destination_path)

                while file.tell() < fileSize:
                    if (fileSize - file.tell()) <= chunk_size:
                        print(dbx.files_upload_session_finish(file.read(chunk_size), cursor, commit))
                    else:
                        dbx.files_upload_session_append_v2(file.read(chunk_size), cursor)
                        cursor.offset = file.tell()
        except Exception as err:
            print("Failed to upload {}\n{}".format(file, err))
        finally:
            file.close()
    print("Finished upload.")
return render_template('complete.html')

Note

You can check out my other projects on the github link below:

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)