I am new to python/flask and am trying to upload an image for a users profile picture during registration. I've taken the backend flask code related to file uploads directly from their documentation found here. When I perform a registration, I receive the HTTP error:
Bad Request The browser (or proxy) sent a request that this server
could not understand.
And in my python console:
no file part
I am using a bootstrap fork "Upload Image w Preview & Filename" found here. Here is my registration form:
<form action="/register" method="POST">
<div class="form-group">
<label for="username">Username</label>
<input type="text" class="form-control" name="username" id="username" placeholder="Username">
</div>
<div class="form-group">
<label for="password">Password</label>
<input type="password" class="form-control" name="password" id="password" placeholder="Password">
</div>
<div class="form-group">
<label for="confirm-password">Confirm Password</label>
<input type="password" class="form-control" name="confirm-password" id="confirm-password" placeholder="Confirm Password">
</div>
<div class="form-group">
<label>Profile Picture</label>
<div class="input-group">
<span class="input-group-btn">
<span class="btn btn-default btn-file">
<button class="btn btn-success">Browse…</button>
<input type="file" id="imgInp" name="file">
</span>
</span>
<input type="text" class="form-control" readonly>
</div>
<img id='img-upload' style="margin-top: 10px;"/>
</div>
<button type="submit" class="btn btn-primary">Submit</button>
</form>
And here is my backend/flask stuff.
from cs50 import SQL
from flask import Flask, flash, redirect, render_template, request, session, url_for
from flask_session import Session
from tempfile import mkdtemp
from werkzeug.exceptions import default_exceptions
from werkzeug.security import check_password_hash, generate_password_hash
from werkzeug.utils import secure_filename
import datetime
import os
UPLOAD_FOLDER = '/static/images'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.secret_key = "super secret key"
app.config["SESSION_TYPE"] = "filesystem"
db = SQL("sqlite:///data.db")
Session(app)
#app.route('/register', methods=['POST'])
def register():
username = request.form.get("username")
password = request.form.get("password")
row = db.execute("SELECT * FROM users WHERE username = :username", username=username)
if not row:
if 'file' not in request.files:
flash('No file part')
print("no file part")
file = request.files['file']
# if user does not select file, browser also
# submit a empty part without filename
if file.filename == '':
flash('No selected file')
print("no selected file")
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))
db.execute("INSERT INTO users (username, passwordHash, pictureUrl) VALUES (:username, :passwordHash, 'static/images/default.jpg')", username=username,passwordHash=generate_password_hash(password))
else:
return apology("Username already exists.")
return redirect("/")
Add the attribute enctype='multipart/form-data' to the form tag. As this attribute enforces the proper HTTP request handling of the form.
Related
This question already has answers here:
Sending data from HTML form to a Python script in Flask
(2 answers)
Get the data received in a Flask request
(23 answers)
Closed 2 months ago.
I'm working on an upload file function for my web tool and I'm facing an issue. The problem is that Flask is not receiving the files from the HTML form. I have already set the route, and created the form tag accordingly to what is required like the method POST and still not working. Am I doing anything wrong?
HTML
<form action="/" method="POST" enctype="multipart/form-data" class="form-horizontal">
<div class="row form-group">
<div class="col-12 col-md-12">
<div class="control-group" id="fields">
<label class="control-label" for="field1">
Requests
</label>
<div class="controls">
<div class="entry input-group upload-input-group">
<input class="form-control" name="fields[]" type="file">
<button class="btn btn-upload btn-success btn-add" type="button">
<i class="fa fa-plus"></i>
</button>
</div>
</div>
<button class="btn btn-primary" type="submit" value="Submit">Upload</button>
</div>
</div>
</div>
</form>
Python/Flask
import os
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename
app=Flask(__name__)
app.secret_key = "secret key"
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024
path = os.getcwd()
# file Upload
UPLOAD_FOLDER = os.path.join(path, 'uploads')
if not os.path.isdir(UPLOAD_FOLDER):
os.mkdir(UPLOAD_FOLDER)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
ALLOWED_EXTENSIONS = set(['xlsx', 'xls'])
def allowed_file(filename):
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
#app.route('/')
def upload_form():
return render_template('index.html')
#app.route('/', methods=['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 file.filename == '':
flash('No file selected for uploading')
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))
flash('File successfully uploaded')
return redirect('/')
else:
flash('Allowed file types are xlsx and xls')
return redirect(request.url)
if __name__ == "__main__":
app.run(host = '127.0.0.1',port = 5000, debug = False)
Try changing the input name to file instead fields[]
<input class="form-control" name="file" type="file">
unfortunately my script no longer works in Flask. I don't know how to fix this. I would be very grateful if you could help me. Here are my codes:
#app.route("/register", methods=["GET", "POST"])
def register():
if request.method == "POST":
username = request.form["uname"]
password = request.form["passwd"]
with open("user.txt", "r") as file:
file.write(username + "\n" + password)
return render_template("register.html")
<form action="/register" method="POST">
<div class="container">
<label for="usm"><b>Username</b></label>
<input type="text" placeholder="Enter Username" name="usm" required>
<label for="pwd"><b>Password</b></label>
<input type="password" placeholder="Enter Password" name="pwd" required>
<button type="submit" name="login">Login</button>
</div>
</form>
This is my error:
werkzeug.exceptions.BadRequestKeyError
werkzeug.exceptions.BadRequestKeyError: 400 Bad Request: The browser (or proxy) sent a request that this server could not understand.
KeyError: 'uname'
Your form is sending a field named usm:
<input ... name="usm">
You're expecting a field named uname:
username = request.form["uname"]
The same stands for pwd/passwd.
Also, you can't .write() to a file opened with the "r" mode.
I am developing a plagiarism detection tool using flask and python and I am getting the error "Method Not Allowed The method is not allowed for the requested URL.". The project allows a user to upload two files to be compared. Whenever I click on the submit button in the html form then the above error occurs. Can you please suggest some changes?
from io import FileIO
from flask import Flask
from flask import render_template
from flask import request
from flask.helpers import url_for
from werkzeug.utils import redirect, secure_filename
import os
import numpy as np
app=Flask(__name__)
#app.route("/")
def home():
return render_template('upload.html')
#app.route("/upload", methods=["GET", "POST"])
def upload():
if request.method == "POST":
f1 = request.files['file1']
f2 = request.files['file2']
return redirect(url_for('user'))
else:
return render_template('upload.html')
#app.route("/")
def user():
return f"<h1>success</h1>"
if __name__=='__main__':
app.run(debug=True)
my html code snippet from upload.html is:
<form enctype="multipart/form-data" method="post">
<label for="file1">Upload first file here:</label>
<input type="file" id="file1" name="file1"><br><br>
<label for="file2">Upload second file here:</label>
<input type="file" id="file2" name="file2"><br><br>
<input type="submit" value="Submit">
</form>
You're missing an action in your form. In your implementation, it tries to send a POST request to home(), not upload(). That's why you're getting Method not allowed message.
<form action="/upload" enctype="multipart/form-data" method="post">
<label for="file1">Upload first file here:</label>
<input type="file" id="file1" name="file1"><br><br>
<label for="file2">Upload second file here:</label>
<input type="file" id="file2" name="file2"><br><br>
<input type="submit" value="Submit">
</form>
The function extract_data() converts uploaded PDF file to JSON data.
Function form_input() is meant to post the JSON data from "extract_data" as default input form values.
Extract_data() generates JSON data but is not redirecting it to form_input()
Below are the functions -
from flask import render_template, redirect, url_for, jsonify
from werkzeug.utils import secure_filename
#app.route("/", methods=["GET", "POST"])
def extract_data(input_module=pdftotext):
if request.method == "POST":
file = request.files["file"]
if file and allowed_file(file.filename):
invoicefile = secure_filename(file.filename)
extracted_str = input_module.to_text(invoicefile)
json_data=jsonify(ext)
session['json_data'] = json_data
return redirect(url_for('form_input', json_data=json_data)
return render_template("extract.html")
Here is extract.html
<html>
<form method='POST' enctype=multipart/form-data>
<input type="file" name="file" class="btn btn-success"></input>
<br>
<button type="submit" value=Upload class="btn btn-warning">Go!
</button>
</form>
</html>
The function form_input() is meant to get the json_data from extract_data() and use it as default form input values.
#app.route("/form_input")
def form_input():
json_data = request.args['json_data']
json_data = session['json_data']
if request.method == 'POST':
submited_item = request.POST['%s' % (value1)]
return render_template("inputdata.html", json_data="json_data")
Here is input_data.html:
<html>
<form method="POST">{{ csrf_token }}
<label>Input data</label>
<input type="text">
{% for item in json_data %}
<input type="checkbox" name="{{ item.value1 }}" value="{{ item.value1 }}"> {{ item.value1 }}<br>
{% endfor %}
<button type="submit" >Submit</button>
</form>
</html>
I'm trying to create a login page using flask and when they enter their correct credentials they will pass, but even when they enter a wrong password and username they will pass anyway!
my form index.html
<form method="post" action="/" role="login">
<h3>ADMIN LOGIN</h3>
<div class="form-group">
<input type="text" name="username" required class="form-control" placeholder="Enter Username" />
<span class="glyphicon glyphicon-user"></span>
</div>
<div class="form-group">
<input type="password" name="password" required class="form-control" placeholder="Enter password" />
<span class="glyphicon glyphicon-lock"></span>
</div>
<button type="submit" name="go" class="btn btn-primary btn-block">Login Now</button>
Reset password
</form>
My identityFace.py as my main
from flask import Flask, session, render_template, request, redirect, g, url_for
import os
import model as dbHandler
app = Flask(__name__)
app.secret_key = 'development key'
#app.route('/', methods=['POST', 'GET'])
def home():
if request.method == 'POST':
username = request.form['username']
password = request.form['password']
# dbHandler.insertUser(username, password)
users = dbHandler.retrieveUsers()
return render_template('home.html', users=users)
else:
return render_template('index.html')
if __name__ == '__main__':
app.run()
and my model.py is
import sqlite3 as sql
def retrieveUsers():
con = sql.connect("ExamsFaceId.db")
cur = con.cursor()
cur.execute("SELECT username, password FROM users")
users = cur.fetchall()
con.close()
return users
It doesn't return an error.
All you did want query for all the users in the database. Nowhere did you verify the entered information
Try implementing your own userExists(username, password) function against the database.
For example,
'SELECT username WHERE username=%s AND password=%s'
Then return cur.rowcount > 0
Back in Flask, check if not db.userExists(username, password), then redirect() back to login.
Alternatively, I think you should really just be using Flask-Admin + Flask-Security plugins because it'll give you this and fix your plain-text password problem.