Search code examples
pythonpython-3.xflaskuuidglob

Flask application not recognising dynamically created directory


I'm trying to create a Flask app in which some of the functionality includes users being able to upload images into their own directory in the static folder.

I've based my code off https://github.com/kirsle/flask-multi-upload, in fact it's basically the same (apart from the AJAX functionality) so I really can't see where I've gone wrong (I've run kirsle's app in my own environment - it works fine).

When I visit /static/uploads/{uuid_goes_here}/img.jpg, I can see the image - so obviously it's being uploaded. However visiting /files/{uuid_goes_here} results in the if not os.path.isdir(location) being executed.

When I comment this code out and try to go straight to complete.html, the {% for file in files %} doesn't seem to run as none of the images appear.

My code is:

app.py

# Route that will process the file upload
@app.route('/upload', methods=['POST'])
def upload():
    form = request.form
    username = current_user.username #for later when I replace uuid's with usernames
    uuid_key = str(uuid4())
    print("Session Key: {}".format(uuid_key))

    target = "static/uploads/{}".format(uuid_key)
    try:
        os.mkdir(target)
    except FileExistsError:
        return "Couldn't create directory {}".format(target)

    for upload in request.files.getlist("file"):
        filename = upload.filename.rsplit("/")[0]
        destination = '/'.join([target, filename])
        print( "Accepting: {}\n and saving to: {}".format(filename, destination))
        upload.save(destination)

    return redirect(url_for('complete', uuid_key=uuid_key))

@app.route("/files/<uuid_key>")
def complete(uuid_key):
    location = "/static/uploads/{}".format(uuid_key)
    if not os.path.isdir(location):
        return "Error! {} not found!".format(location)

    files = []
    for file in glob.glob("{}/*.*".format(location)):
        fname = file.split(os.sep)[-1]
        files.append(fname)

    return render_template('complete.html', uuid=uuid_key, files=files)

complete.html

{% extends 'layout.html' %}

{% block content %}

{% for file in files %}
    <h2>{{ file }}</h2>
    <img src="{{ url_for('static', filename='/uploads/{}/{}'.format(uuid, file)) }}">
{% endfor %}

{% endblock %}

post.html

{% extends 'layout.html' %}

{% block content %}

    <form action="upload" method="post" enctype="multipart/form-data">
        <input type="file" name="file" accept="image/*"><br /><br />
        <input type="submit" value="Upload">
      </form>

{% endblock %}

I've compared my code to kirsle's and I can't see where I've gone wrong.


Solution

  • You've put a / in front of what should have been a relative path:

    location = "static/uploads/{}".format(uuid_key)
        if not os.path.isdir(location):
    

    Assuming your file structure is:

    app.py
    static/
    templates/
    

    and this logic is in app.py