Search code examples
pythonflaskflask-wtformsflask-appbuilder

Can not upload file/image in flaskapp


I have created a form in html/php, and using flask for backend.

Everything is working perfect except when I am trying to upload image I am always seeing the error:

error is**"UnboundLocalError: local variable 'filename' referenced before assignment"**

my flaskapp code snippet is

@app.route('/apple', methods=['GET', 'POST'])
def apple():
  onlineAppForm = RegForm()
  if request.method == 'POST':
    try:
        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))
    except Exception as e:
        print "Form without file "+str(e)
    return render_template("apply2.html", data=data, filename=filename, form=onlineAppForm)

this is my upload folder

UPLOAD_FOLDER = 'static/uploads'
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.secret_key = os.urandom(24)

I am not getting where the error is.

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

this is my form

<tr>
    <td class="sectionheading">Upload Scanned Copies</td>
</tr>
<tr>
    <td height="12">&nbsp;</td>
</tr>
<tr id="photosignthumb_span" height="40">
    <td align="left" valign="middle" width="100%">&nbsp;<b>
        <span class="mandatory">*</span>
        Please upload scanned copies of your photo </b>
        <input type="file" name="photo" id="photofile"  
         method="post"/><br>
        Please upload your recent passport size photograph:max 
        80KB(Only JPEG and JPG formats)
    </td>
</tr>
<tr id="photosignthumb_span" height="40">
    <td align="left" valign="middle" width="100%">&nbsp;<b>
        <span class="mandatory">*</span>
        Please upload scanned copies of your signature </b> 
        <input type="file" name="sign" id="signfile" 
        method="post"/><br>
        Please upload your recent passport size photograph:max 
        80KB(Only JPEG and JPG formats)
    </td>
</tr>

Solution

  • filename existence depends on couple of conditions:

    1 - file = request.files['file']
    2 - if file and allowed_file(file.filename):
    3 - No exception is raised.

    So, if any of the above didn't happen, then filename won't spring into existence and hence your error message.

    EDIT:

    Quoting from flask docs on file upload:

    1. A tag is marked with enctype=multipart/form-data and an is placed in that form.
    2. The application accesses the file from the files dictionary on the request object.
    3. Use the save() method of the file to save the file permanently somewhere on the filesystem.

    Looking at the form your provided it seems you don't have any form block, you should have something like:

    <form action="/apple" method="post" enctype="multipart/form-data">
    <tr>
        <td class="sectionheading">Upload Scanned Copies</td>
    </tr>
    <tr>
        <td height="12">&nbsp;</td>
    </tr>
    <tr id="photosignthumb_span" height="40">
        <td align="left" valign="middle" width="100%">&nbsp;<b>
            <span class="mandatory">*</span>
            Please upload scanned copies of your photo </b>
            <input type="file" name="photo" id="photofile"  
             method="post"/><br>
            Please upload your recent passport size photograph:max 
            80KB(Only JPEG and JPG formats)
        </td>
    </tr>
    <tr id="photosignthumb_span" height="40">
        <td align="left" valign="middle" width="100%">&nbsp;<b>
            <span class="mandatory">*</span>
            Please upload scanned copies of your signature </b> 
            <input type="file" name="sign" id="signfile" 
            method="post"/><br>
            Please upload your recent passport size photograph:max 
            80KB(Only JPEG and JPG formats)
        </td>
    </tr>
    </form>