How to Take and Store Uploaded Code Python
Writing a multi-file-upload Python-spider web app with user hallmark
Providing an piece of cake method for collaborators to upload files to a filestore without the demand for them to understand whatsoever code whatever
When building a webserver we often wish to present an idea or topic. In the example of a static website, this can be done by including the relevant data within the source files. In more than dynamic examples, an API (application programming interface) can be used to pre-procedure information before returning information technology to the user.
In this example, we design a elementary flask app which but requires a user key and a spider web browser to piece of work. The idea behind this is that anyone can use it, and it is a device (and operating system), independent.
Creating the flask app
As usual, we start by installing the relevant libraries for the server. The simplest way to do this is through the employ of pip (pythons packet manager).
pip install flask, werkzeug
The upload-page template
Next, create our HTML template for the login folio. To exercise this we commencement in our application directory and make a new file named templates
. Within this, nosotros create a file named upload.html
and paste the following code within it.
In essence, nosotros take a form
which contains our password input
, a file upload input
and a submit button. When working this will look as follows
Setting up the upload options
Side by side, we define a config file for our upload options. To do this create a file named config.py
in your main app binder. Within this, we can specify a maximum accepted file size, the upload destination, and what file extensions we can choose to have. Copy the code below into config.py
and adjust accordingly.
A note on file types: File extensions do not guarantee file type and we should avoid executing any uploaded files. This is why we later on introduce a password — such that only canonical users tin upload.
A flask template
Nosotros begin with a bones flask template, which imports our data and serves the upload.html
folio when navigating to http://127.0.0.1:4000/upload
Upload file checks
Now we have our app, nosotros can add a number of functions to ensure that nosotros accept the right directory, and if not create it.
if not os.path.isdir(upload_dest):
os.mkdir(upload_dest)
Nosotros can set the maximum file upload size (using the value from config.py
)
app.config['MAX_CONTENT_LENGTH'] = file_mb_max * 1024 * 1024
and also check the file extensions (again divers in config.py
)
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', i)[1].lower() in extensions
Personally, I accept added these between app.secret
and the @app.route
sections within the code.
What to exercise on upload
Finally, we have yet to tell the program what to do upon uploading. Nosotros do and so this by parsing the mail request from the upload page. For information on what this means — have a read of:
Hither we check if the request.method
is a POST, and if then handle any files attached. The showtime department deals with an empty request, whilst the second iterates through each file, checks that they have the correct 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 found, endeavor again.')
return redirect(asking.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(s) uploaded')
return redirect('/upload')
Testing the usage case
Finally, earlier continuing on to adding passwords, nosotros want to make certain that the upload functions equally intended. To do this we run the python script, navigate to http://127.0.0.1:4000/upload, select a few files and click upload. If this has been successful, and you are using the configuration above, your files should at present reside within an uploads_folder
directory nested in the same folder as your app.
Adding an encrypted database for user authentication
So far we accept created a Flask app which we tin can use to upload files. Side by side, we want to add a layer of basic security, such that we can track what files have been uploaded and by whom. In improver, this allows us to reject anyone not authorised to commit information to the directory.
Installing pysqlcipher3
We begin by installing our database tool. This can sometimes crusade bug for people, so the installation instructions for Mac and Linux take 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
We beginning past connecting to the database. If y'all have ever used databases earlier, the pysqlcipher syntax is pretty much the aforementioned as sqlite, or any postgresql libraries. We begin 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/test.db
cursor = conn.cursor()
Finally, nosotros need to specify an encryption cardinal for our database in order to be able to access the data.
cursor.execute("PRAGMA key='%s'"%app_key)
If you practice not practice this, or employ a dissimilar key, you will receive the following error: 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 central, we can now create a tabular array to store our values. We do this by executing a create table
SQL control with the cursor execute
part. The simplest usage example would require a proper noun and an upload_key.
cursor.execute(
'''
CREATE Table IF NOT EXISTS upload (
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
proper name TEXT NOT NULL,
upload_key TEXT UNIQUE
);
'''
)
Additionally, I accept set a condition that each primal has to be unique, as we are not using a user proper name to log on.
Finally, we take to commit our new table to the database and close it.
conn.commit()
## conn.shut()
## shut only when we have finished everything, otherwise we have to reopen the database each time
Adding a User
Nosotros need users to be able to use the upload tool, then nosotros can add together some using the insert
command.
cursor.execute(
'''
INSERT INTO upload (proper noun, dir, uploadcode)
VALUES ("bob", "bobs top secret upload key")
'''
conn.commit()
Reading the Database
As a cheque, nosotros want to meet if there is a proper name associated with the upload_key. This can be done with the select
function, coupled with a where
conditional.
user_code = 'bobs tiptop hole-and-corner upload key' cursor.execute('select * from upload where uploadcode="%south"'%user_code) result = cursor.fetchall() # get all the results e.g. [("bob",)]
Stringing information technology all together
At present we have a database and an upload script, we can combine the 2.
Opening the database
Firstly we add together the required library
from pysqlcipher3 import dbapi2 as sqlite3
# from config import app_key, db_loc # already imported
under the from config_simple import *
line.
Reading the password
If y'all are using the HTML code from earlier, we already have a password input field :<p> upload_key: <input proper name="psw" blazon="password" /></p>
As this is within the submission grade we can read information technology as part of the Mail request in the @app.route
wrapper.
user_code = str(request.grade.go('psw'))
We combine this with our database read to grade a conditional checking if there is anyone with that access fundamental /countersign.
cursor.execute('select * from upload where uploadcode="%s"'%user_code)
result = cursor.fetchall() if len(result)==0:
flash('Not a valid Lawmaking')
return redirect(request.url)
However, since the database can only be opened and read from the same computational thread equally the website we demand to place
conn = sqlite3.connect(db_loc)
cursor = conn.cursor()
cursor.execute("PRAGMA key='%due south'"%app_key)
before the cursor.execute
block, and a conn.shut()
subsequently the result =
line. (run into app.py in the GitHub repo at the terminate)
Conclusion
And there we have it — the virtually basic of submission boxes which allows for the uploading of files past pre-approved users. At that place are however a number of improvements that y'all may wish to make (these are all in the additional files shown in the GitHub repository below).
- Checking the filename string for an extension can cause problems. Files may exist named incorrectly, or fifty-fifty not have an extension (equally was the instance with many of my files). Instead, nosotros can filter on the
file.mimetype
values. These are of the formatprototype/png
etc. - Drag and Driblet uploading. It can often exist cumbersome to manually select files, peculiarly if they are in different locations. Dragging them from a file browser makes life much simpler for the user.
- Automatic uploads. Another mutual mistake is to select a file, but forget to click submit. Having a window that works immediately after you drop a file in it can help assist productivity and user satisfaction
- File previews. If the user is uploading images, it can always be helpful to accept miniature previews bachelor. This allows a last-minute check such that you are not repeatedly submitting the aforementioned file.
- File failure indicators. Although there is a message informing us of the upload condition, a visual cue (ie a lighter preview paradigm) makes information technology much easier to see if something has not worked.
- Unique download spaces — if you have many users, information technology can become confusing which file belongs to who (not to mention the overwriting trouble). Instead, we can add a designated space for each user, and save the paths within the database.
Adding all the boosted suggestions above and nosotros the following output.
Here nosotros see, 2 files take failed, with i succeeding in the middle. In this instance, it was due to invalid user credentials and an intentionally invalid filetype.
Disclaimer: this is not the most secure method of checking credentials, nevertheless for the purposes of many tasks information technology can exist a perfectly adequate solution.
Codebase
All the example lawmaking for this tutorial has been dumped (quite literally) into a Github repository.
If you accept any improvements, feel free to submit a pull request.
blackwellwhost1993.blogspot.com
Source: https://towardsdatascience.com/writing-a-multi-file-upload-python-web-app-with-user-authentication-8f75064b819a
0 Response to "How to Take and Store Uploaded Code Python"
Post a Comment