Raunak Deshmukh Raunak Deshmukh - 1 month ago 8
Python Question

List and serve files from GridFS with Flask

I have files stored in GridFS. I want to show the user a list of files, and allow them to download them. I have the following code that saves the file to the server, but I'm not sure how to serve the file to the client. How do I serve files from GridFS with Flask?

<form id="submitIt" action="/GetFile" method="Post">
{% for file in List %}
<input type="checkbox" name="FileName" value={{file.strip('u').strip("'")}}>{{file.strip('u').strip("'")}}<br>
{% endfor %}
<a href="#" onclick="document.getElementById('submitIt').submit();">Download</a>
</form>




@app.route('/GetFile',methods=['POST'])
def GetFile():
connection = MongoClient()
db=connection.CINEfs_example
fs = gridfs.GridFS(db)
if request.method == 'POST':
FileName=request.form.getlist('FileName')
for filename in FileName:
EachFile=fs.get_last_version(filename).read()
with open(filename,'wb') as file2:
file2.write(EachFile)
return 'files downloaded'

Answer

Rather than saving the file retrieved from GridFS to the server's filesystem, pass it on to the client in response. You cannot send more than one file at once, so you'll have to remove the ability to select multiple files. You don't need a form at all, just pass the name in the url and create a list of links in the template.

@app.route('/get-file/<name>')
@app.route('/get-file')
def get_file(name=None):
    fs = gridfs.GridFS(MongoClient().CINEfs_example)

    if name is not None:
        f = fs.get_last_version(name)
        r = app.response_class(f, direct_passthrough=True, mimetype='application/octet-stream')
        r.headers.set('Content-Disposition', 'attachment', filename=name)
        return r

    return render_template('get_file.html', names=fs.list())

get_file.html:

<ul>{% for name in names %}
<li><a href="{{ url_for('get_file', name=name) }}">{{ name }}</a></li>
{% endfor %}</ul>
Comments