Skip to content

Instantly share code, notes, and snippets.

@artisonian
Created July 27, 2010 19:24
Show Gist options
  • Save artisonian/492713 to your computer and use it in GitHub Desktop.
Save artisonian/492713 to your computer and use it in GitHub Desktop.
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
Copy link

@bastianh
Copy link

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
Copy link

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
Copy link

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

@alfredfrancis
Copy link

@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