0

I need to upload image file to MongoDB using mongoengine and Bottle framework. There is my python code:

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)

And template:

<!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>

When I try upload a image, it gives an error:

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'

Is it possible to upload an image file from Bottle request to MongoDB?

I just tried to save the file:

@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))

It returns error:

ValueError('I/O operation on closed file',)

Then I tried open file before save upload:

@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())

Error:

ValueError('read of closed file',)

What am I doing wrong?

2 Answers 2

0

First all img_src is instance of class bottle.FileUpload. It not have read(). Basically save the file and open again. Make test below. Good luck!

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)
2
0

true that if img_src is a bottle.FileUpload instance it has no .read() method

but then img_src.file is a _io.BufferedRandom so it has .read() method.

so you can do directly :

file_h = img_src.file
img = Image.open(file_h)

still, trying to open it with Pillow 2.5 Image.open() gave me a "ValueError: read of closed file" (exception came from Image.open() and fp.read(16) call in it)

upgrading Bottle from 0.12 to 0.12.7 did the trick and this exception vanished. hope it helps.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.