pythonflaskwtformsflask-wtformsflask-uploads

Deleting/moving file with Flask


I have setup uploading a profile picture with wtforms, flask_wtf, and flask_uploads libraries, which uploads a file to the server in the static folder of Flask. I want to prevent users from uploading more than one profile picture, and want to delete their old picture. I have successfully detected the file on the server with an IF statement, but cannot figure out how to delete the file or simply move the file to another folder that I can manually delete.

I have tried the Python function os.remove(), but was always getting an error that the specified file did not exist. From what I was reading, you can't use such a function with Flask because the server is actively running and it would mess with the active processes.

What would be the best idea to deal with this? I was hoping there is a library function to first check if the file name is in use, and just overwrite the file, but Couldn't find anything in the library documentations. I recognize that I could just upload the profile picture to the SQL table into a BLOB, but read that was not an optimal solution.

Let me know what your suggestion would be to solve the problem of preventing users from uploading too many files!

What I have so far:

import os, sys
from flask import Flask, render_template, flash, request, url_for, redirect, session, send_file, send_from_directory
# WTForms
from wtforms import Form, BooleanField, TextField, PasswordField, SelectField, RadioField, TextAreaField, DateField, DateTimeField, StringField, validators
from wtforms.widgets import TextArea
from wtforms.validators import DataRequired
from flask_wtf import FlaskForm, RecaptchaField
from flask_wtf.file import FileField, FileRequired, FileAllowed
from werkzeug.utils import secure_filename
from flask_uploads import UploadSet, configure_uploads, IMAGES, patch_request_class
from MySQLdb import escape_string as thwart

app = Flask(__name__)
#### PROFILE PIC UPLOAD ####
# Based after https://gist.github.com/greyli/81d7e5ae6c9baf7f6cdfbf64e8a7c037
# For uploading files
PROF_PIC_UPLOAD_FOLDER = 'static/user_info/prof_pic'
ALLOWED_EXTENSIONS = set(['png', 'jpg', 'jpeg', 'gif'])
app.config['UPLOADED_PHOTOS_DEST'] = os.getcwd()
photos = UploadSet('photos', IMAGES)
configure_uploads(app, photos)
patch_request_class(app)  # set maximum file size, default is 16MB

class ProfilePictureForm(FlaskForm):
    prof_pic = FileField(validators=[FileAllowed(photos, u'Image only!')])

@app.route('/profile_picture_upload/', methods=['GET','POST'])
def profile_picture_upload():
    form = ProfilePictureForm()
    cid = str(session['clientcid'])
    first_name = session['first_name']
    static_url = url_for('static', filename='user_info/prof_pic/')
    default_prof_pic = 'http://localhost:5000/_uploads/photos/static/user_info/prof_pic/default.jpg'
    user_prof_pic = cid+first_name+'.png'
    if form.validate_on_submit():
        filename = photos.save(form.prof_pic.data, folder=PROF_PIC_UPLOAD_FOLDER,name=cid+first_name+'.png')
        file_url = photos.url(filename)
        # Checks if the prof_pic is set yet. if set, then dont need to delete the old picture on the server
        if session['prof_pic'] != 'http://localhost:5000/_uploads/photos/static/user_info/prof_pic/default.jpg':
            #need to delete or move the old prof_pic if it was set! Prevents users from adding too many pictures
            flash("You already have a file on the server!")
        #If the user_prof_pic is there, then  
        session['prof_pic'] = file_url
        c, conn = connection()
        c.execute("UPDATE cpersonals SET prof_pic = %s WHERE cid = (%s)", (file_url, cid))
        conn.commit()
        c.close()
        conn.close()
    else:
        file_url = None

    return render_template('profile_picture_upload.html', form=form, file_url=file_url)

Solution

  • At first you will make sure that the file exists in your location

    import os.path
    
    os.path.exists(file_path)
    

    Also check in debug mode - problem with chmod folder.