如何使用Bottle框架和Mongoengine将图像文件上传到MongoDB?
我需要通过mongoengine和Bottle框架把图片文件上传到MongoDB。以下是我的Python代码:
from bottle import Bottle, run, route, post, debug, request, template, response
from mongoengine import *
connect('imgtestdb')
app = Bottle()
class Image(Document):
img_id = IntField()
img_src = ImageField()
@app.route('/img/<image>')
def get_img(image):
img = Image.objects(img_id=image)[0].img_src
response.content_type = 'image/jpeg'
return img
@app.route('/new')
def new_img_form():
return template('new.tpl')
@app.post('/new')
def new_img():
img_id = request.forms.get('id')
img_src = request.files.get('upload')
img = Image()
img.img_id = img_id
img.img_src.put(img_src, content_type = 'image/jpeg')
img.save()
app.run(host='localhost', port=8080, debug=True, reloader=True)
还有模板:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<form action="/new" method="post" enctype="multipart/form-data">
Image ID: <input type="text" name="id" />
Select a file: <input type="file" name="upload" />
<input type="submit" value="Start upload" />
</form>
</body>
</html>
当我尝试上传一张图片时,出现了一个错误:
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/mongoengine/fields.py", line 1311, in put
img = Image.open(file_obj)
File "/usr/lib/python3/dist-packages/PIL/Image.py", line 2000, in open
prefix = fp.read(16)
AttributeError: 'FileUpload' object has no attribute 'read'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/local/lib/python3.4/dist-packages/bottle.py", line 862, in _handle
return route.call(**args)
File "/usr/local/lib/python3.4/dist-packages/bottle.py", line 1728, in wrapper
rv = callback(*a, **ka)
File "./imgtest.py", line 38, in new_img
img.img_src.put(img_src, content_type = 'image/jpeg')
File "/usr/local/lib/python3.4/dist-packages/mongoengine/fields.py", line 1314, in put
raise ValidationError('Invalid image: %s' % e)
mongoengine.errors.ValidationError: Invalid image: 'FileUpload' object has no attribute 'read'
从Bottle请求中上传图片文件到MongoDB是否可行?
我只是尝试保存文件:
@app.route('/upload', method='POST')
def do_upload():
img_id = request.forms.get('imgid')
upload = request.files.get('upload')
upload.save('tmp/{0}'.format(img_id))
结果返回了错误:
ValueError('I/O operation on closed file',)
然后我尝试在保存上传之前打开文件:
@app.route('/upload', method='POST')
def do_upload():
upload = request.files.get('upload')
with open('tmp/1.jpg', 'w') as open_file:
open_file.write(upload.file.read())
错误:
ValueError('read of closed file',)
我到底哪里做错了?
2 个回答
0
确实,如果 img_src 是一个 bottle.FileUpload 的实例,它是没有 .read() 方法的。
但是,img_src.file 是一个 _io.BufferedRandom 对象,所以它是有 .read() 方法的。
所以你可以直接这样做:
file_h = img_src.file
img = Image.open(file_h)
不过,尝试用 Pillow 2.5 的 Image.open() 打开它时,我遇到了一个 "ValueError: read of closed file" 的错误(这个错误是从 Image.open() 和里面的 fp.read(16) 调用引发的)。
把 Bottle 从 0.12 升级到 0.12.7 后,这个问题就解决了,这个错误也消失了。
希望这对你有帮助。
0
首先,img_src是一个bottle.FileUpload类的实例。它没有read()这个方法。基本上,它是用来保存文件的,然后再打开。下面是一个测试代码。祝你好运!
import os
from bottle import route, run, template, request
from mongoengine import Document, IntField, ImageField, connect
connect('bottle')
class Image(Document):
img_id = IntField()
img_src = ImageField()
@route('/home')
def home():
return template('upload')
@route('/upload', method='POST')
def do_upload():
img_id = request.forms.get('id')
img_src = request.files.get('upload')
name = img_src.filename
# your class ...
img = Image()
img.img_id = img_id
# img_src is class bottle.FileUpload it not have read()
# you need save the file
img_src.save('.') # http://bottlepy.org/docs/dev/_modules/bottle.html#FileUpload
# mongoengine uses PIL to open and read the file
# https://github.com/python-imaging/Pillow/blob/master/PIL/Image.py#L2103
# open temp file
f = open(img_src.filename, 'r')
# saving in GridFS...
img.img_src.put(f)
img.save()
return 'OK'
run(host='localhost', port=8080, debug=True)