Cherry
Cherry

Reputation: 33

"Not Found" Error when uploading photo to website and submitting on flask python

I am attempting to create code that allows users to input a photo and have that photo save to the folder '/home/HassanSherien/mysite/Shape_Image'. I have followed the steps given in the below link but I keep getting an error that states "Not Found, the requested URL was not found on the serves. if you entered the URL manually, please check your spelling and try again."

Python:

 import os
 from flask import Flask, request, redirect, url_for
 from werkzeug.utils import secure_filename
UPLOAD_FOLDER = '/home/HassanSherien/mysite/Shape_Image'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

def upload_file():
    if request.method == 'POST':
    if 'file' not in request.files:
        flash('No file part')
        return redirect(request.url)
    file = request.files['file']
    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))

HTML:

<form action="myform.cgi"> 
<input type="file" name="fileupload" value="fileupload" 
id="file`upload"> 
<label for="fileupload"> Select a file to upload</label>
 <br>
<input type="image" src="/wp-content/uploads/sendform.png" 
alt="Submit" width="100"> 
</form>

I am also given an error on the line if file and allowed_file(file.filename): that says "undefined name 'allowed_file'"

Upload image in Flask

Upvotes: 1

Views: 1209

Answers (1)

v25
v25

Reputation: 7631

You haven't assigned a route to your upload_file function. This should be done on the line immediately above the function definition:

@app.route('/upload', methods=['POST'])
def upload_file():
    # rest of your code

Also you'll need to make the form's action correspond to this URL:

<form action="/upload" method='POST'>

In Flask templates you can generate this URL automatically, based on the function name:

<form action="{{ url_for('upload_file') }}" method='POST'>

Also the only input fields in your form should be:

<input type="file" name="file" id="file_upload" /> 
<input type="submit />

Notice I've set name="file" which corresponds to what your Python code accepts. See this answer I've just posted for why this is. The offical docs on this are a bit confusing as they reuse the term 'file' in multiple places, which I think confuses people, especially new-comers.


I am also given an error on the line if file and allowed_file(file.filename): that says "undefined name 'allowed_file'"

Sounds like you haven't defined that function as per the docs:

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

EDIT as per comment:

now my website will allow people to upload photos and it will automatically submit (since despite there being no submit button the code knows to right after something is uploaded submit it)

Sorry: You need a second input tag for the submit button: just <input type='submit' /> towards the end of the form.

Once the user has selected the file they wish to upload, they then click this button and a POST request is sent to the server with the data.

to url_for('upload_file') which was '/home/HassanSherien/mysite/Shape_Image' in my case.

When the form is actually rendered (prior to any upload activity) the form's action attribute will be the return value of {{url_for('file_upload')}} This will be /upload (as set in the @app.route line). This makes the form submit to: http://example.com/upload. Don't confuse this with the path entered in UPLOAD_FOLDER which is server side.

In the code which handles the upload the following line joins the path specified as UPLOAD_FOLDER to the value of filename:

file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))

To make this a bit easier to read, it's the same as:

full_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
file.save(full_path)

That second line is you calling the save method of the file object, providing the full path as the argument. This literally saves the file to disk.

If you're finding that this isn't happening, then check the server console as you may need to set directory permissions, etc.

This function should also return something like a redirect to someplace else on the site.

Upvotes: 2

Related Questions