Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A simple GridFS server built with Flask
from flask import Flask, request, redirect, url_for, make_response, abort
from werkzeug import secure_filename
from pymongo import Connection
from pymongo.objectid import ObjectId
from gridfs import GridFS
from gridfs.errors import NoFile
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])
DB = Connection().gridfs_server_test
FS = GridFS(DB)
app = Flask(__name__)
def allowed_file(filename):
return '.' in filename and \
filename.rsplit('.', 1)[1] in ALLOWED_EXTENSIONS
@app.route('/', methods=['GET', 'POST'])
def upload_file():
if request.method == 'POST':
file = request.files['file']
if file and allowed_file(file.filename):
filename = secure_filename(file.filename)
oid = FS.put(file, content_type=file.content_type, filename=filename)
return redirect(url_for('serve_gridfs_file', oid=str(oid)))
return '''
<!DOCTYPE html>
<html>
<head>
<title>Upload new file</title>
</head>
<body>
<h1>Upload new file</h1>
<form action="" method="post" enctype="multipart/form-data">
<p><input type="file" name="file"></p>
<p><input type="submit" value="Upload"></p>
</form>
<a href="%s">All files</a>
</body>
</html>
''' % url_for('list_gridfs_files')
@app.route('/files')
def list_gridfs_files():
files = [FS.get_last_version(file) for file in FS.list()]
file_list = "\n".join(['<li><a href="%s">%s</a></li>' % \
(url_for('serve_gridfs_file', oid=str(file._id)), file.name) \
for file in files])
return '''
<!DOCTYPE html>
<html>
<head>
<title>Files</title>
</head>
<body>
<h1>Files</h1>
<ul>
%s
</ul>
<a href="%s">Upload new file</a>
</body>
</html>
''' % (file_list, url_for('upload_file'))
@app.route('/files/<oid>')
def serve_gridfs_file(oid):
try:
file = FS.get(ObjectId(oid))
response = make_response(file.read())
response.mimetype = file.content_type
return response
except NoFile:
abort(404)
@RedBeard0531

This comment has been minimized.

Copy link

@RedBeard0531 RedBeard0531 commented Jul 27, 2010

@bastianh

This comment has been minimized.

Copy link

@bastianh bastianh commented Mar 13, 2011

instead of reading the file into memory you can directly pass it to the response .. like

from werkzeug import Response
....
@frontend.route('/files/<oid>')
def serve_gridfs_file(oid):
    try:
        file = FS.get(ObjectId(oid))
        return Response(file, mimetype=file.content_type, direct_passthrough=True)
    except NoFile:
        abort(404)

this will need much less memory since the file is not read into memory

@mattgorecki

This comment has been minimized.

Copy link

@mattgorecki mattgorecki commented Aug 29, 2012

You can also compile Nginx with the GridFS module and serve files directly from Nginx. As of the time of this comment, I've compiled Nginx 1.3.5 with GridFS module 0.8 and am using MongoDB 2.0.7.

https://github.com/mdirolf/nginx-gridfs

@kevgathuku

This comment has been minimized.

Copy link

@kevgathuku kevgathuku commented Jul 14, 2015

A more up to date example is available at https://gist.github.com/kevgathuku/51e30f08a552084b1130

@alfredfrancis

This comment has been minimized.

Copy link

@alfredfrancis alfredfrancis commented Apr 22, 2020

@frontend.route('/files/')
def serve_gridfs_file(oid):
try:
file = FS.get(ObjectId(oid))
return Response(file, mimetype=file.content_type, direct_passthrough=True)
except NoFile:
abort(404)

true

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment