Jason Strimpel
Jason Strimpel

Reputation: 15526

400 Bad Request error during Flask file upload?

This is the view function used to generate a file upload form and process it (yes this comes directly from the Flask docs):

transaction_blueprint = Blueprint(
    "transaction", __name__, template_folder="../templates", url_prefix="/transactions"
)

@transaction_blueprint.route("/upload", methods=["GET", "POST"])
def upload_select_file():
    print(request.method)
    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.get("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)
        # allowed_file is defined elsewhere
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join("/tmp", filename))
            return jsonify({"success": True})
    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>
    <p>%s</p>
    """ % "<br>".join(os.listdir("/tmp",))

Upon submitting the form from http://localhost:8000/transactions/upload, I receive the 400 bad request error. I am testing with a simple text file that is about 15kb in size. As far as I can tell, the HTML is well formed:

<form method="post" enctype="multipart/form-data">
  <input type="file" name="file">
  <input type="submit" value="Upload">
</form>

I've searched for two days and learned this error occurs when the file input's name attribute is not found in the Flask view endpoint. I handle for that using request.files.get("file"). Further In my case, upon submitting the form, the method is not being reached (server log does not even print "POST"). This makes sense as the 400 is a client error but still...

Is there something with using Blueprints that's breaking this? What am I doing wrong here?

Upvotes: 1

Views: 1357

Answers (1)

Jason Strimpel
Jason Strimpel

Reputation: 15526

Adding the csrf token did it...

<input type="hidden" name="csrf_token" value="{{ csrf_token() }}"/>

Upvotes: 1

Related Questions