3

I got a web service that allows user to upload files to the "Uploads" folder. These files are accessible by name using the /uploads/filename.ext path. However, unless I know the precise filename, I cannot access files.

How can I programmatically generate and serve a webpage that will provide an index of all files in the /uploads folder if the user types /uploads?

from flask import Flask
from flask import Response, jsonify, request, redirect, url_for
import os
from werkzeug.utils import secure_filename


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


#retrieve uploads by name
@app.route('/uploads/<filename>')
def uploaded_file(filename):
    return send_from_directory(app.config['UPLOAD_FOLDER'],
                               filename)


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

################# AUDIO NOTES UPLOAD  ####################
@app.route('/', methods=['GET', 'POST'])
def upload_file():
    print 'upload file'

    try:
        os.stat(app.config['UPLOAD_FOLDER'])
    except:
        os.mkdir(app.config['UPLOAD_FOLDER'])

    if request.method == 'POST':
        file = request.files['file']
        print 'filename: ' + file.filename

        if file and allowed_file(file.filename):
            print 'allowing file'
            filename = secure_filename(file.filename)
            print 'secure filename created'
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            print 'file saved'
            return redirect(url_for('uploaded_file',filename=filename))

    return '''
        <!doctype html>
        <title>Upload new File</title>
        <h1>Upload new File</h1>
        <form action="" method=post enctype=multipart/form-data>
        <p><input type=file name=file>
        <input type=submit value=Upload>
        </form>
        '''



################## APP LAUNCH POINT ############################
if __name__ == '__main__':
    app.run(host='0.0.0.0')

############################################################
TheSoundDefense
  • 6,753
  • 1
  • 30
  • 42
Alex Stone
  • 46,408
  • 55
  • 231
  • 407

2 Answers2

4

Slightly off-topic, since the original question was for python, but you can generate a static HTML directory listing using tree in HTML output mode:

tree -H "/uploads" -L 1 > index.html

The option -L 1 limits the listing only for the current folder. Without it, the list will recursively include all the subfolders.

It is available in standard repos for most distros. On ubuntu you can install it with sudo apt install tree.

Related: How can I create a simple index.html file which lists all files/directories?

ccpizza
  • 28,968
  • 18
  • 162
  • 169
1

It sounds like you need to list all of the files that are inside the Upload folder. Python's os.listDir() should be able to help you. I am using listDir to get all the names of the files, and then passing them to my view as a render parameter.

def get_files_from_directory(path):
    list_of_files = []
    if len(path) > 0:
        list_of_files = [ f for f in listdir(path) if isfile(join(path,f)) ]
    return list_of files

You could then do something like this:

@app.route('/uploads/<path>')
def list_uploads(path):
    list_of_uploads = get_files_from_directory(path)
    #render your template with this list_of_uploads.

My recommendation is that you don't give users the option to pass their own paths. This could be a huge security risk for you. Instead, create a URL like: 'http://www.yourwebsite.com/uploads/list'. Which will pass a path you set in your server-side code to get the files they want to look at. This will be much, much safer.

dustin
  • 101
  • 5
  • This is great, now I need to find how to programmatically generate html or insert this into an existing template – Alex Stone Jul 30 '14 at 21:28
  • Check out Flask's render_template(), it allows you to pass a template and a model of variables to render on the page! – dustin Jul 31 '14 at 00:13