Flask Upload File Not Found - python

I want to make a file uploader using Python, Flask, and HTML. If I upload a file I get:
Not Found
The requested URL was not found on the server. If you entered the URL
manually please check your spelling and try again.
import os
from flask import Flask, request, redirect, url_for, render_template
from werkzeug.utils import secure_filename
UPLOAD_FOLDER = './user/Tom/Files/'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == ['POST']:
if 'file' not in request.files:
flash('Geen Bestand')
return redirect(request.url)
file = request.files['file']
if file.filename == '':
flash('Geen Bestand')
return redirect(request.url)
if not os.path.exists("user/Tom/Files/"):
os.makedirs("user/Tom/Files/")
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("index.html")
if __name__ == ('__main__'):
app.run(debug=True, port=8000)
<!DOCTYPE html>
<html>
<head>
<title>Upload a File!</title>
</head>
<body>
<form method="post" action="user/Tom/Files/" enctype="multipart/form-data">
<input type="file" id="customFile" name="file">
<input type="submit" name="Upload" value="Upload">
</form>
</form>
</body>
</html>

I deleted the action and the value
Now i have this:
<form method="post" enctype="multipart/form-data">
<input type="file" id="customFile" name="file">
<input type="submit" name="Upload">
</form>
But now it stay on de index.html but doesnt upload it to /user/Tom/Files/ ?

Related

Flask / Python: Modify uploaded file data before saving

I would like to be able to upload a csv file, then have a script in python do some modifications to the file, and finally save the file after changes to a specific folder. I have something like this, but I don't know why it doesn't work:
import os
from flask import Flask, render_template, request, redirect, url_for, send_from_directory
from werkzeug.utils import secure_filename
app = Flask(__name__)
UPLOAD_FOLDER = 'C:/Users/tkp/Desktop/uploads_files'
app.config['UPLOAD_EXTENSIONS'] = ['.csv']
app.config['UPLOAD_PATH'] = UPLOAD_FOLDER
#app.route('/')
def index():
files = os.listdir(app.config['UPLOAD_PATH'])
return render_template('index.html', files=files)
#app.route('/', methods=['POST'])
def upload_files():
uploaded_file = request.files['file']
filename = secure_filename(uploaded_file.filename)
if filename != '':
uploaded_file.stream.seek(0)
f = uploaded_file.read()
#some change in the file
f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
return redirect(url_for('index'))
#app.route('/Users/tkp/Desktop/uploads_files/<filename>')
def upload(filename):
return send_from_directory(app.config['UPLOAD_PATH'], filename)
And HTML file:
<!doctype html>
<html>
<head>
<title>File Upload</title>
</head>
<body>
<h1>File Upload</h1>
<form method="POST" action="" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="Convert"></p>
</form>
<hr>
</body>
</html>
Is it possible to perform such an operation on the fly or do you have to save the uploaded file first?
You are doing everything correctly, except the f.save(...) definition.
When you do f = uploaded_file.read(), the f is the result of the .read() operation, which is bytes, not a file.
You have to open another file and save the contents to it.
Don't forget to .decode() the bytes, to make it a string.
Here's a working snippet:
#app.route('/', methods=['POST'])
def upload_files():
uploaded_file = request.files['file']
filename = secure_filename(uploaded_file.filename)
if filename != '':
uploaded_file.stream.seek(0)
f = uploaded_file.read().decode()
# WE don't want any failures
f = f.replace("FAIL", "SUCCESS")
filename_to_save = os.path.join(app.config['UPLOAD_PATH'], filename)
with open(filename_to_save, "w") as file_to_save:
file_to_save.write(f)
return {"status": "OK"}
It could probably be a typo in your action attribute. Change this line:
<form method="POST" action="" enctype="multipart/form-data">
to this:
<form method="POST" action="/" enctype="multipart/form-data">

How can I enable the user to post a music file in their post using Flask?

My site will enable users to post something like a blog post, but with a audio file attached to it, so that other user can listen to it while reading. I made a dummy post so that I could check a few things and also a simple route.
from flask import render_template
from site import app
posts = [{
'title': 'asdf',
'text': 'asdf',
'file': "2.mp3"
}]
#app.route("/")
#app.route("/home")
def home():
return render_template('home.html', posts=posts)
I also have the home.html template
<!DOCTYPE html>
<html>
<head>
<title>Site</title>
</head>
<body>
{% for post in posts %}
<h1>
{{ post.title }}
</h1>
<h2>
{{ post.text }}
</h2>
<audio controls>
<source src="{{ post.file }}" type="audio/mpeg">
</audio>
{% endfor %}
</body>
</html>
My logic was simple: if the 2.mp3 file is in the same directory as the home.html file, then the music should play. But it doesn't. I don't really have an idea what should I do. I'm using Python 3.7.
This is actually a bit more complex than that because they're is two options.
The first is the "easy one" and what's you're trying to achieve. Having the file in the static folder along with the home template and return it to the user via the template.
To achieve that, you just need to modify your template a bit:
<source src="{{ url_for('static', filename=post.file) }}" type="audio/mpeg">
However, that will not work if the file is not in your static folder (i.e. if the user uploads the file himself).
For that, you will need to follow the steps in the docs and you will probably end up to something close to the following:
import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
from flask import send_from_directory
UPLOAD_FOLDER = '/path/to/the/uploads'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', '.mp3'}
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/', 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>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<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)

Getting a CSRF token is missing error when trying to upload an image to a flask app

I'm trying to upload an image to my flask app using flask-docs methods but this error keeps popping up:
400 Bad Request, CSRF Token is missing.
Here's the view functions:
# file uploading (avatar)
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#login_required
#app.route('/upload_avatar', methods=['POST', 'GET'])
def upload_avatar():
if request.method == 'POST':
if 'file' not in request.files:
flash('No file part')
return redirect(url_for('user'))
file = request.files.get('file', False)
if file.filename == '':
flash('No selected file')
return redirect(url_for('user'))
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
file.save = (os.path.join(app.config['UPLOAD_FOLDER'], current_user.username))
return redirect(url_for('uploaded_file', filename=filename))
return render_template('upload_avatar.html')
#login_required
#app.route('/uploaded_file')
def uploaded_file(filename):
return send_from_directory(app.config['UPLOAD_FOLDER'], filename)
And this is the template:
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form method=post enctype=multipart/form-data>
<input type=file name=file>
<input type=submit value=Upload>
</form>
i do have csrf.protect initialized
csrf = CsrfProtect()
csrf.init_app(app)
UPLOAD_FOLDER = '/mnt/d/work/mysnsite/app/uploads/'
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}
CKEDITOR_ENABLE_CSRF = True
WTF_CSRF_ENABLED = False
WTF_CSRF_SECRET_KEY = 'secretkey'
app.config['SECRET_KEY'] = 'secretkey2'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
I've tried adding {{ form.csrf_token() }} and {{ form.hidden_tag() }} but it doesn't seem to work as there is no form initialized in my view function..

Flask HTTP Server won't allow upload of multiple files at once

import os
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename
UPLOAD_FOLDER = '/home/ubuntu/shared/'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
file = request.files['file']
if file:
filename = secure_filename(file.filename)
file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
return redirect(url_for('index'))
return """
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method="post" enctype="multipart/form-data">
<p><input type="file" multiple="" name="file">
<input type="submit" value="Upload">
</form>
<p>%s</p>
""" % "<br>".join(os.listdir(app.config['UPLOAD_FOLDER'],))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8000, debug=False)
If I launch the server and select 2 files through the form, it only uploads one of them. I tried for serveral hours and read about 15 topics on it, including the documentation.
Nada :c
Edit:
I also tried changing:
file = request.files['file']
into:
file = request.files.getlist('file')
would not work either. The type of quotes have no effect either. Wasn't that a python3 thing?
import os, ssl
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename
UPLOAD_FOLDER = '/home/ubuntu/shared/'
certfile = "/home/ubuntu/keys/fullchain.pem"
keyfile = "/home/ubuntu/keys/privkey.pem"
ecdh_curve = "secp384r1"
cipherlist = "ECDHE-ECDSA-AES256-GCM-SHA384 ECDHE-ECDSA-CHACHA20-POLY1305"
sslcontext = ssl.create_default_context(purpose=ssl.Purpose.CLIENT_AUTH)
sslcontext.options |= ssl.OP_NO_TLSv1
sslcontext.options |= ssl.OP_NO_TLSv1_1
sslcontext.protocol = ssl.PROTOCOL_TLSv1_2
sslcontext.set_ciphers(cipherlist)
sslcontext.set_ecdh_curve(ecdh_curve)
sslcontext.load_cert_chain(certfile, keyfile)
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
my_data = request.files.getlist('file')
my_pass = request.form['password']
if my_data and my_pass == 'yakumo':
for file in my_data:
my_handler(file)
return redirect(url_for('index'))
return """
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file multiple name=file>
<input type="password" name="password" value="">
<input type=submit value=Upload>
</form>
<p>%s</p>
""" % "<br>".join(os.listdir(app.config['UPLOAD_FOLDER'],))
def my_handler(f):
filename = secure_filename(f.filename)
f.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=8000, ssl_context=sslcontext, threaded=True, debug=False)
I made a very rookie mistake and didn't for-loop over the multiple files being uploaded. The code here was tested without issues with 4 simultaneous file uploads. I hope it will be useful to someone.
Edit: Code updated with some sweet TLS_1.2 and a password field. Enjoy a reasonably secure upload server. Password is transferred over HTTPS.

Upload two different file in two different fields

I'm using flask to develop webapp and I have two different files to upload to two different locations and as far as I search through the internet I only find explanation to upload one or multiple together in one file field and it works fine.
here is the code i used to upload one file:
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
file = request.files['file']
if file > 0:
filename = secure_filename(file.filename)
file.save(os.path.join(UPLOAD_FOLDER , filename))
return redirect(url_for('index'))
can someone help me with that
The name of the input will be the key which you retrieve the file from request.files
html:
<input type="file" name="first_file" />
<input type="file" name="second_file" />
Flask:
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
first_file = request.files['first_file']
second_file = request.files['second_file']
... # do stuff with files
Documentation.
here is the whole code:
import os
from flask import Flask, request, redirect, url_for
from werkzeug import secure_filename
import sys
sys.path.insert(0, '/home/muteb/Desktop/test')
UPLOAD_FOLDER = '/home/muteb/Desktop/test/'
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
#app.route("/", methods=['GET', 'POST'])
def index():
if request.method == 'POST':
file1 = request.files['file1']
file2 = request.files['file2']
if file1 > 0:
filename1 = secure_filename(file1.filename)
file1.save(os.path.join(UPLOAD_FOLDER , filename1))
if file2 > 0:
filename2 = secure_filename(file2.filename)
file2.save(os.path.join(UPLOAD_FOLDER , filename2))
return redirect(url_for('index'))
return """
<!doctype html>
<title>Upload new File</title>
<h1>Upload new File</h1>
<form action="" method=post enctype=multipart/form-data>
<p><input type=file name=file1>
<input type=file name=file2>
<input type=submit value=Upload>
</form>
<p>%s</p>
""" % "<br>".join(os.listdir(app.config['UPLOAD_FOLDER'],))
if __name__ == "__main__":
app.run(host='0.0.0.0', port=5002, debug=True)

Categories