deny already uploaded files in flask - python

Hi I am uploading files with flask.
Somehow something recently broke and we want to deny already existing files. Which it used to do automatically. Now while adjusting the function I don't see it working somehow. I tried a couple things and I am stuck on this now. We do a curl request from another server and the upload is automated. We have a frontend on there but purely cause of the current state of the application what is relevant is that we list a directory and we want to forbid overwritting those files.
DENY_UPLOADED_IMAGES = os.listdir(f)
#app.route("/upload")
def upload():
if request.method == 'POST':
# check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
# submit an empty part without filename
if 'file' in DENY_UPLOADED_IMAGES:
flash('File already uploaded')
return redirect(request.url)
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return render_template('upload.html')

DENY_UPLOADED_IMAGES = os.listdir(f)
This, which is at the global level, only reads the list of currently uploaded files when your application is launched. Filenames won't be added to this list if they were uploaded since the app (or worker) restarted.
Probably better to check each one at the time of upload:
if os.path.exists(file.filename):
flash('File already uploaded')
return redirect(request.url)
This may still be open to a race condition if run with multiple WSGI workers.

Related

How to generate a unique name for each uploaded file?

I am building a Flask website, and I want to save a path of a file to my sqlite database
I have a "create" view, where user uploads an image and it gets stored in a folder
#app.route('/create', methods = ["GET", "POST"])
#login_required
def create():
if request.method == "POST":
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return render_template('create.html')
I want to store a 'path' to each image in my sqlite database. To do this, I think, every filename should be unique. So how should I generate a unique name for each uploaded file?
An easy way to generate a unique file name would be to just use a numbering system (first file being 1, then increasing by 1). Like so:
counter = 0 #put this at the beginning of your script
then when creating file name:
counter += 1
filename = counter
If you do not want your files to be named just numbers you could hash the number to generate a unique code, like so:
counter += 1
filename = counter.encode("utf-8")
filename = hashlib.sha224(filename).hexdigest()
If doing the latter, you would want to save this code somewhere associated with the user so you can open it again.

How to upload a file to your website hosted by Heroku?

I developed a website that would take a user provided file and extract relevant data out of it, I used Python/Flask for the backend and the website is stored in Heroku.
The application is working fine on my local machine, but when I run it in Heroku, whenever I attempt to upload/process a file I get this message on Heroku's logs:
2022-02-14T17:27:48.000421+00:00 app[web.1]: FileNotFoundError: [Errno 2] No such file or directory: '/application/uploads/report.html'
My python code that goes around the file uploading is:
app.config['UPLOAD_PATH'] = './application/uploads'
#app.route('/read', methods=['GET', 'POST'])
def read():
form = ReadForm()
if form.validate_on_submit():
if request.method == 'POST':
files = request.files.getlist('read')
for file in files:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return redirect(url_for('show'))
return render_template('read.html', form=form)
How do I make the uploaded files available to my application? After reading the file, the application just delete it.
I saw a question with a very similar title as mine, here:
How to upload file on website hosted by Heroku?
And one of the answers there, suggests using Amazon's S3, is it the only solution?
#buran pointed me to another post here which helped me solving the issue: Python Flask upload file to app folder on server (heroku)
I added the following to my path definition:
base_path = os.path.dirname(__file__)
So the final one would be:
# Path for the files upload part
app.config['UPLOAD_PATH'] = '/uploads'
base_path = os.path.dirname(__file__)
Then when uploading a file I refer to the path like this:
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(base_path + "/" + app.config['UPLOAD_PATH'], filename))
So, instead of:
file.save(os.path.join(app.config['UPLOAD_PATH'], filename))
I used:
file.save(os.path.join(base_path + "/" + app.config['UPLOAD_PATH'], filename))

Uploading files to an Amazon S3 bucket using flask Python

I am trying to upload a file using the flask and boto3 module to one of my Amazon S3 buckets. My code does not just upload the file, but it also uploads the folder where that file is stored. Can somebody please help me with that. If I am already providing the path of the file in the code which you can see below. How does the upload thing work in the Html button?
#app.route("/upload", methods=['POST'])
def upload():
if request.method == "POST":
f = request.files['file']
f.save(os.path.join(UPLOAD_FOLDER, f.filename))
upload_file(f"readme/{f.filename}", BUCKET)
return redirect("/storage")
Folders do not actually exist in Amazon S3. If you upload a file to a folder, the folder will magically 'appear'. Later, if you delete all files in the (pretend) folder, then the folder will disappear.
If you use the "Create Folder" button in the S3 management console, it actually creates a zero-length object with the same name of the folder. This 'forces' the folder to appear because it contains an object (but that object isn't displayed).
So, when you say "it also uploads the folder where that file is stored", you are probably just seeing the folder name 'appear'. It probably only uploaded one file.

Upload wav file and save in directory using python

Here is my db Model
db.define_table('manage_music_file',
Field('action_is', requires=IS_IN_SET(('Insert',
'Remove')),notnull=True, default='Insert'),
Field('wav_file', 'upload', comment='Please upload your .wav
file',requires=IS_NOT_EMPTY()
)
This my controller
def index():
form = SQLFORM(db.manage_music_file)
#return dict(form=form)
if form.process().accepted:
logger.debug(('here we ahve a form',form))
errors = []
if form.vars['action_is'] == 'Insert':
logger.debug(('where file need to place'))
if not form.vars['wav_file']:
errors.append('No file given')
return 'No file given'
else:
dirname='/var/lib/asterisk/sounds/musiconhold'
logger.debug(('where file need to place', dirname))
import os.path
completeName = os.path.join(dirname, form.vars.wav_file)
file1 = open(completeName, "a")
file1.close()
return dict(form=form)
I am sending wav file A.wav in upload
But i am receiving file in this format in directory
manage_music_file.wav_file.a70701e297ffec7a.412e776176.wav
I want same name A.wav in directory as well
A.wav
Hamza, web2py renames these files as a security measure, to help prevent directory traversal attacks.

Flask-Uploads IOError: [Errno 2] No such file or directory

So, I've been trying to add an image uploader to my code, but I've been running into issues. Even though I thought I had my upload_folder configured properly, I keep getting errors like: IOError: [Errno 2] No such file or directory: '/static/uploads/compressor.jpg' even though the file/directory exists.
Here's the code:
in config.py
UPLOAD_FOLDER = 'static/uploads'
in init.py
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
in views.py
#app.route('/fileupload', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
#check if the post request has the file part
if 'file' not in request.files:
flash('No file part')
return redirect(request.url)
file = request.files['file']
# if user does not select file, browser also
#submit an empty part without filename
if file.filename == '':
flash('No selected file')
return redirect(request.url)
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('uploaded_file',
filename=filename))
return '''
<!doctype html>
<title>Upload new File</title>
<h>UPload new file</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file>
<input type=submit value=Upload>
</form>
'''
#app.route('/uploads/<filename>')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'],
filename)
My folder structure is as follows
/project folder
--/app
----/static
--------/uploads
----/templates
----_init__.py
----views.py
--config.py
When I use /tmp/ to store it in memory the uploader works no problem. I assume it's not looking in the proper path for my folder. Can anyone help here? I'm a very amateur python developer.
Both /tmp and /static/uploads/.., are absolute paths. And your code is looking in the / folder instead of looking in your project's folder. You should use the absolute path to point at your folder /path/to/your/project/static/uploads/.. or use a path relative to the code being executed such as ./static/uploads.
You can also use the following snippet to generate the absolute path:
from os.path import join, dirname, realpath
UPLOADS_PATH = join(dirname(realpath(__file__)), 'static/uploads/..')
This worked for me:
basedir = os.path.abspath(os.path.dirname(__file__))
file.save(os.path.join(basedir, app.config['UPLOAD_FOLDER'], filename))
#jidesakin's solutions works but here is another solution:
Move your uploads folder from static directory back to your project directory where your app folder is, the folder where your app and environment folders are.
Your structure will be like:
'projectfolder
--/app
--config.py
--__init__.py
------/static
------/templates
------config
--uploads
Then change the content of you upload folder from 'static/uploads' to 'uploads' ...

Categories

Resources