前期準備 通過 pip 或 easy_install 安裝了 pymongo 之后, 就能通過 Python 調教 mongodb 了. 接著安裝個 flask 用來當 web 服務器. 當然 mongo 也是得安裝的. 對于 Ubuntu 用戶, 特別是使用 Server 12.04 的同學, 安裝最新版要略費些周折, 具體說是 sudoapt
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
echo 'deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen' | sudo tee /etc/apt/sources.list.d/mongodb.list
sudo apt-get update
sudo apt-get install mongodb-10gen
pip install Pillow
easy_install Pillow
app = flask.Flask(__name__) @app.route('/upload', methods=['POST']) @app.route('/') if __name__ == '__main__':import flask
app.debug = True
def upload():
f = flask.request.files['uploaded_file']
print f.read()
return flask.redirect('/')
def index():
return '''
'''
app.run(port=7777)
upload
函數中, 使用 flask.request.files[KEY]
獲取上傳文件對象, KEY 為頁面 form 中 input 的 name 值app = flask.Flask(__name__) def save_file(f): @app.route('/upload', methods=['POST'])import pymongo
import bson.binary
from cStringIO import StringIO
app.debug = True
db = pymongo.MongoClient('localhost', 27017).test
content = StringIO(f.read())
db.files.save(dict(
content=bson.binary.Binary(content.getvalue()),
))
def upload():
f = flask.request.files['uploaded_file']
save_file(f)
return flask.redirect('/')
bson.binary.Binary
對象, 再把它扔進 mongodb 就可以了.db.files.find()
content
這個域幾乎肉眼無法分辨出什么東西, 即使是純文本文件, mongo 也會顯示為 Base64 編碼.@app.route('/f/ @app.route('/upload', methods=['POST'])def save_file(f):
content = StringIO(f.read())
c = dict(content=bson.binary.Binary(content.getvalue()))
db.files.save(c)
return c['_id']
def serve_file(fid):
f = db.files.find_one(bson.objectid.ObjectId(fid))
return f['content']
def upload():
f = flask.request.files['uploaded_file']
fid = save_file(f)
return flask.redirect('/f/' + str(fid))
upload
函數會跳轉到對應的文件瀏覽頁. 這樣一來, 文本文件內容就可以正常預覽了, 如果不是那么挑剔換行符跟連續空格都被瀏覽器吃掉的話.bson.errors.InvalidId
; 其二, 找不到對象 (!), 這時 pymongo 會返回 None
.@app.route('/f/
def serve_file(fid):
import bson.errors
try:
f = db.files.find_one(bson.objectid.ObjectId(fid))
if f is None:
raise bson.errors.InvalidId()
return f['content']
except bson.errors.InvalidId:
flask.abort(404)
allow_formats = set(['jpeg', 'png', 'gif']) def save_file(f):from PIL import Image
content = StringIO(f.read())
try:
mime = Image.open(content).format.lower()
if mime not in allow_formats:
raise IOError()
except IOError:
flask.abort(400)
c = dict(content=bson.binary.Binary(content.getvalue()))
db.files.save(c)
return c['_id']
@app.route('/f/def save_file(f):
content = StringIO(f.read())
try:
mime = Image.open(content).format.lower()
if mime not in allow_formats:
raise IOError()
except IOError:
flask.abort(400)
c = dict(content=bson.binary.Binary(content.getvalue()), mime=mime)
db.files.save(c)
return c['_id']
def serve_file(fid):
try:
f = db.files.find_one(bson.objectid.ObjectId(fid))
if f is None:
raise bson.errors.InvalidId()
return flask.Response(f['content'], mimetype='image/' + f['mime'])
except bson.errors.InvalidId:
flask.abort(404)
db.files.drop()
清掉原來的數據.def save_file(f): @app.route('/f/import datetime
content = StringIO(f.read())
try:
mime = Image.open(content).format.lower()
if mime not in allow_formats:
raise IOError()
except IOError:
flask.abort(400)
c = dict(
content=bson.binary.Binary(content.getvalue()),
mime=mime,
time=datetime.datetime.utcnow(),
)
db.files.save(c)
return c['_id']
def serve_file(fid):
try:
f = db.files.find_one(bson.objectid.ObjectId(fid))
if f is None:
raise bson.errors.InvalidId()
if flask.request.headers.get('If-Modified-Since') == f['time'].ctime():
return flask.Response(status=304)
resp = flask.Response(f['content'], mimetype='image/' + f['mime'])
resp.headers['Last-Modified'] = f['time'].ctime()
return resp
except bson.errors.InvalidId:
flask.abort(404)
db.files.ensureIndex({sha1: 1}, {unique: true})
def save_file(f): sha1 = hashlib.sha1(content.getvalue()).hexdigest()import hashlib
content = StringIO(f.read())
try:
mime = Image.open(content).format.lower()
if mime not in allow_formats:
raise IOError()
except IOError:
flask.abort(400)
c = dict(
content=bson.binary.Binary(content.getvalue()),
mime=mime,
time=datetime.datetime.utcnow(),
sha1=sha1,
)
try:
db.files.save(c)
except pymongo.errors.DuplicateKeyError:
pass
return c['_id']
c['_id']
將會是一個不存在的數據 ID. 修正這個問題, 最好是返回 sha1
, 另外, 在訪問文件時, 相應地修改為用文件 SHA-1 訪問, 而不是用 ID.app = flask.Flask(__name__) def save_file(f): sha1 = hashlib.sha1(content.getvalue()).hexdigest() @app.route('/f/ @app.route('/upload', methods=['POST']) @app.route('/') if __name__ == '__main__':import hashlib
import datetime
import flask
import pymongo
import bson.binary
import bson.objectid
import bson.errors
from cStringIO import StringIO
from PIL import Image
app.debug = True
db = pymongo.MongoClient('localhost', 27017).test
allow_formats = set(['jpeg', 'png', 'gif'])
content = StringIO(f.read())
try:
mime = Image.open(content).format.lower()
if mime not in allow_formats:
raise IOError()
except IOError:
flask.abort(400)
c = dict(
content=bson.binary.Binary(content.getvalue()),
mime=mime,
time=datetime.datetime.utcnow(),
sha1=sha1,
)
try:
db.files.save(c)
except pymongo.errors.DuplicateKeyError:
pass
return sha1
def serve_file(sha1):
try:
f = db.files.find_one({'sha1': sha1})
if f is None:
raise bson.errors.InvalidId()
if flask.request.headers.get('If-Modified-Since') == f['time'].ctime():
return flask.Response(status=304)
resp = flask.Response(f['content'], mimetype='image/' + f['mime'])
resp.headers['Last-Modified'] = f['time'].ctime()
return resp
except bson.errors.InvalidId:
flask.abort(404)
def upload():
f = flask.request.files['uploaded_file']
sha1 = save_file(f)
return flask.redirect('/f/' + str(sha1))
def index():
return '''
'''
app.run(port=7777)
原文地址:Flask / MongoDB 搭建簡易圖片服務器, 感謝原作者分享。
聲明:本網頁內容旨在傳播知識,若有侵權等問題請及時與本網聯系,我們將在第一時間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com