Where to Upload Python Files to Run Always

Providing an piece of cake method for collaborators to upload files to a filestore without the demand for them to empathise any lawmaking whatsoever

Photograph by Hullo I'thou Nik 🎞 on Unsplash

When building a webserver we ofttimes wish to present an idea or topic. In the case of a static website, this tin can exist done by including the relevant information inside the source files. In more dynamic examples, an API (awarding programming interface) tin can be used to pre-procedure information before returning it to the user.

In this example, we design a simple flask app which but requires a user key and a web browser to work. The idea backside this is that anyone tin can use it, and it is a device (and operating system), contained.

Creating the flask app

As usual, we start by installing the relevant libraries for the server. The simplest style to do this is through the use of pip (pythons packet manager).

            pip install flask, werkzeug          

The upload-page template

Next, create our HTML template for the login page. To do this we first in our awarding directory and make a new file named templates . Inside this, we create a file named upload.html and paste the following lawmaking within it.

In essence, we have a form which contains our password input, a file upload input and a submit button. When working this will wait equally follows

Output from upload_simple.html

Setting up the upload options

Next, we define a config file for our upload options. To practice this create a file named config.py in your main app folder. Inside this, nosotros tin can specify a maximum accustomed file size, the upload destination, and what file extensions we can cull to take. Re-create the lawmaking below into config.py and conform accordingly.

A note on file types: File extensions exercise not guarantee file type and we should avoid executing any uploaded files. This is why we later introduce a password — such that just canonical users can upload.

A flask template

Nosotros brainstorm with a bones flask template, which imports our information and serves the upload.html folio when navigating to http://127.0.0.1:4000/upload

Upload file checks

Now we take our app, we can add a number of functions to ensure that we have the correct directory, and if not create it.

            if not os.path.isdir(upload_dest):
os.mkdir(upload_dest)

We can set the maximum file upload size (using the value from config.py)

            app.config['MAX_CONTENT_LENGTH'] = file_mb_max * 1024 * 1024          

and besides check the file extensions (again divers in config.py)

            def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in extensions

Personally, I have added these between app.secret and the @app.road sections within the code.

What to do on upload

Finally, nosotros have yet to tell the programme what to exercise upon uploading. Nosotros practice so this by parsing the post request from the upload folio. For information on what this means — have a read of:

Here we check if the request.method is a POST, and if and then handle whatever files attached. The offset section deals with an empty request, whilst the second iterates through each file, checks that they have the right file extension, and if so saves them to our desired location (upload_dest).

            @app.route('/upload', methods=['Post'])
def upload_file():
if request.method == 'Post':
if 'files[]' not in request.files:
flash('No files establish, try again.')
return redirect(request.url)
files = request.files.getlist('files[]') for file in files:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.bring together( upload_dest, filename))
flash('File(due south) uploaded')
return redirect('/upload')

Testing the usage instance

Finally, earlier continuing on to adding passwords, we want to make sure that the upload functions as intended. To practise this we run the python script, navigate to http://127.0.0.ane:4000/upload, select a few files and click upload. If this has been successful, and you are using the configuration higher up, your files should now reside inside an uploads_folder directory nested in the same folder as your app.

Adding an encrypted database for user authentication

And then far we accept created a Flask app which we tin can utilize to upload files. Next, we want to add a layer of bones security, such that we can track what files have been uploaded and past whom. In addition, this allows us to reject anyone not authorised to commit data to the directory.

Installing pysqlcipher3

We begin by installing our database tool. This tin can sometimes cause problems for people, and then the installation instructions for Mac and Linux have been included below.

MAC

            brew install SQLCipher
pip install pysqlcipher3

LINUX

            sudo apt install sqlcipher libsqlcipher0 libsqlcipher-dev
sudo -H pip3 install pysqlcipher3
python3 -c 'import pysqlcipher3; print(pysqlcipher3.__path__)'

Connecting to the database

Nosotros start by connecting to the database. If you have ever used databases earlier, the pysqlcipher syntax is pretty much the same as sqlite, or any postgresql libraries. We brainstorm by importing the libraries

            from pysqlcipher3 import dbapi2 as sqlite3
from config import app_key, db_loc

And and so connecting to the database:

            conn = sqlite3.connect(db_loc)# where this is /path/exam.db
cursor = conn.cursor()

Finally, we need to specify an encryption fundamental for our database in order to exist able to access the data.

            cursor.execute("PRAGMA key='%s'"%app_key)          

If you practice not practice this, or use a unlike cardinal, you will receive the following fault: DatabaseError: file is not a database when trying to read information from the database schema.

Creating the Database

Having opened our database, and entered our primal, we tin now create a tabular array to store our values. Nosotros do this by executing a create table SQL control with the cursor execute function. The simplest usage case would require a name and an upload_key.

            cursor.execute(
'''
CREATE TABLE IF NOT EXISTS upload (
id INTEGER Non Nothing PRIMARY Central AUTOINCREMENT,
name TEXT NOT NULL,
upload_key TEXT UNIQUE
);
'''
)

Additionally, I have set a status that each key has to be unique, as nosotros are not using a user name to log on.

Finally, nosotros have to commit our new table to the database and close it.

            conn.commit()
## conn.close()
## shut only when we accept finished everything, otherwise we have to reopen the database each fourth dimension

Adding a User

We need users to be able to utilize the upload tool, so we can add together some using the insert command.

            cursor.execute(
'''
INSERT INTO upload (name, dir, uploadcode)
VALUES ("bob", "bobs top secret upload central")
'''
conn.commit()

Reading the Database

As a check, nosotros want to see if at that place is a proper name associated with the upload_key. This can exist washed with the select role, coupled with a where provisional.

            user_code = 'bobs height secret upload central'            cursor.execute('select              * from upload              where              uploadcode="%s"'%user_code)            result = cursor.fetchall() # go all the results east.k. [("bob",)]          

Stringing it all together

Now we accept a database and an upload script, we can combine the 2.

Opening the database

Firstly we add the required library

            from pysqlcipher3 import dbapi2 equally sqlite3
# from config import app_key, db_loc # already imported

under the from config_simple import *line.

Reading the password

If you are using the HTML lawmaking from earlier, we already have a countersign input field :<p> upload_key: <input name="psw" type="password" /></p>

As this is inside the submission form nosotros can read information technology equally part of the POST request in the @app.road wrapper.

            user_code = str(asking.form.get('psw'))          

Nosotros combine this with our database read to grade a provisional checking if there is anyone with that access cardinal /countersign.

            cursor.execute('select * from upload where uploadcode="%s"'%user_code)
result = cursor.fetchall()
if len(event)==0:
flash('Not a valid Code')
return redirect(request.url)

Still, since the database can only be opened and read from the same computational thread as the website nosotros need to place

            conn = sqlite3.connect(db_loc)
cursor = conn.cursor()
cursor.execute("PRAGMA primal='%south'"%app_key)

before the cursor.execute block, and a conn.shut() subsequently the result = line. (see app.py in the GitHub repo at the end)

Conclusion

And there nosotros have it — the most basic of submission boxes which allows for the uploading of files past pre-approved users. In that location are nonetheless a number of improvements that you may wish to make (these are all in the additional files shown in the GitHub repository beneath).

  • Checking the filename string for an extension can cause problems. Files may be named incorrectly, or even non accept an extension (every bit was the instance with many of my files). Instead, nosotros can filter on the file.mimetype values. These are of the format paradigm/png etc.
  • Elevate and Drib uploading. It can ofttimes be cumbersome to manually select files, especially if they are in different locations. Dragging them from a file browser makes life much simpler for the user.
  • Automatic uploads. Another common mistake is to select a file, but forget to click submit. Having a window that works immediately subsequently you drop a file in it tin aid aid productivity and user satisfaction
  • File previews. If the user is uploading images, it tin can always be helpful to accept miniature previews available. This allows a last-minute cheque such that you are non repeatedly submitting the same file.
  • File failure indicators. Although there is a message informing united states of america of the upload condition, a visual cue (ie a lighter preview image) makes information technology much easier to see if something has not worked.
  • Unique download spaces — if you take many users, it can go disruptive which file belongs to who (non to mention the overwriting problem). Instead, we can add a designated infinite for each user, and save the paths within the database.

Adding all the boosted suggestions above and we the following output.

Hither nosotros see, two files have failed, with ane succeeding in the heart. In this case, it was due to invalid user credentials and an intentionally invalid filetype.

Disclaimer: this is not the near secure method of checking credentials, however for the purposes of many tasks information technology tin can be a perfectly adequate solution.

Codebase

All the example code for this tutorial has been dumped (quite literally) into a Github repository.

If you accept any improvements, feel free to submit a pull request.

lilleyablity.blogspot.com

Source: https://towardsdatascience.com/writing-a-multi-file-upload-python-web-app-with-user-authentication-8f75064b819a

0 Response to "Where to Upload Python Files to Run Always"

Post a Comment

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel