PIL&x2500;Python图像库─;通过CherryPy将图像缩略图上载到SQLAlchemy数据库
我正在尝试从客户端的本地文件将图像及其缩略图保存到SQLAlchemy数据库中。将HTML表单上载到CherryPy服务器。然后,使用Python图像库(PIL)处理图像以获得缩略图。最后,结果应该保存在SQLAlchemy数据库中,但失败了,可能是因为缩略图 注意:我尝试在不将缩略图临时保存在文件中的情况下执行此操作。由于数据已经在RAM中可用,我不喜欢将其保存在文件夹中,然后将其添加到数据库,最后从文件夹中删除。做这样的事是不对的 编辑4结尾的解决方案 关于ObjectImage类的表,PIL&x2500;Python图像库─;通过CherryPy将图像缩略图上载到SQLAlchemy数据库,python,sqlalchemy,python-imaging-library,image-uploading,cherrypy,Python,Sqlalchemy,Python Imaging Library,Image Uploading,Cherrypy,我正在尝试从客户端的本地文件将图像及其缩略图保存到SQLAlchemy数据库中。将HTML表单上载到CherryPy服务器。然后,使用Python图像库(PIL)处理图像以获得缩略图。最后,结果应该保存在SQLAlchemy数据库中,但失败了,可能是因为缩略图 注意:我尝试在不将缩略图临时保存在文件中的情况下执行此操作。由于数据已经在RAM中可用,我不喜欢将其保存在文件夹中,然后将其添加到数据库,最后从文件夹中删除。做这样的事是不对的 编辑4结尾的解决方案 关于ObjectImage类的表, 这
这是我必须使用的
这是一个要求!Python 2.7也是如此
# ! /usr/bin/env python
# -*- coding: utf-8 -*-
# image_upload.py
""" Python 2.7.3
Cherrypy 3.2.2
PostgreSQL 9.1
psycopy2 2.4.5
SQLAlchemy 0.7.10
PIL 1.1.7
"""
以下是到PostgreSQL数据库的SQLAlchemy连接。它作为“会话”存储在CherryPy会话中,并作为s1检索。
这样就没人会把s1当成樱桃色的东西
column type attributes
----------------------------------------
id int PRIMARY KEY
object_id int REFERENCES Obeject(id) ON DELETE CASCADE
filename varchar(252)
image bytea
thumbnail bytea
preview boolean
简约Python代码:
pg = sqlalchemy.create_engine(
'postgresql://{}:{}@{}:{}/{}'.format(
user, password, server, port, data))
Session = sessionmaker(bind=pg)
cherrypy.session['session'] = Session
File "image_upload.py", line 1621, in store_image
s1.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 710, in commit
self.transaction.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 368, in commit
self._prepare_impl()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 347, in _prepare_impl
self.session.flush()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1734, in flush
self._flush(objects)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1805, in _flush
flush_context.execute()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/unitofwork.py", line 331, in execute
rec.execute(self)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/unitofwork.py", line 475, in execute
uow
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/persistence.py", line 64, in save_obj
table, insert)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/persistence.py", line 558, in _emit_insert_statements
execute(statement, params)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1449, in execute
params)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1584, in _execute_clauseelement
compiled_sql, distilled_params
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1691, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/default.py", line 331, in do_execute
cursor.execute(statement, parameters)
TypeError: can't escape instance to binary
CherryPy回溯:
"""
The variable "image_file"
comes directly from the POSTed dictionary.
image_file = kwargs['image_file']
"""
s1 = cherrypy.session.get('session')
image_entry = {}
img = StringIO.StringIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image.copy()
thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
image_entry['thumbnail'] = thumb.copy()
image_entry['object_id'] = chosen_one
image_entry['filename'] = image_file.filename
image_entry['preview'] = 't'
s1.add(ObjecteImage(**image_entry))
s1.commit() #line 1621
s1 = cherrypy.session.get('session')
image_entry = {}
img = StringIO.StringIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image_file
[ ... the same as above ... ]
s1.add(ObjecteImage(**image_entry))
s1.commit() #line 1621
在第二次尝试中,我尝试至少直接插入最初上传的文件,以检查是否有任何更改
简约Python代码:
pg = sqlalchemy.create_engine(
'postgresql://{}:{}@{}:{}/{}'.format(
user, password, server, port, data))
Session = sessionmaker(bind=pg)
cherrypy.session['session'] = Session
File "image_upload.py", line 1621, in store_image
s1.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 710, in commit
self.transaction.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 368, in commit
self._prepare_impl()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 347, in _prepare_impl
self.session.flush()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1734, in flush
self._flush(objects)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 1805, in _flush
flush_context.execute()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/unitofwork.py", line 331, in execute
rec.execute(self)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/unitofwork.py", line 475, in execute
uow
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/persistence.py", line 64, in save_obj
table, insert)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/persistence.py", line 558, in _emit_insert_statements
execute(statement, params)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1449, in execute
params)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1584, in _execute_clauseelement
compiled_sql, distilled_params
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/base.py", line 1691, in _execute_context
context)
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/default.py", line 331, in do_execute
cursor.execute(statement, parameters)
TypeError: can't escape instance to binary
CherryPy回溯:
"""
The variable "image_file"
comes directly from the POSTed dictionary.
image_file = kwargs['image_file']
"""
s1 = cherrypy.session.get('session')
image_entry = {}
img = StringIO.StringIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image.copy()
thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
image_entry['thumbnail'] = thumb.copy()
image_entry['object_id'] = chosen_one
image_entry['filename'] = image_file.filename
image_entry['preview'] = 't'
s1.add(ObjecteImage(**image_entry))
s1.commit() #line 1621
s1 = cherrypy.session.get('session')
image_entry = {}
img = StringIO.StringIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image_file
[ ... the same as above ... ]
s1.add(ObjecteImage(**image_entry))
s1.commit() #line 1621
如何将PIL图像中的实例或PIL图像缩略图中的无转换为二进制文件?或者是一个缓冲区,顺便说一句。。。我甚至不知道我真正需要什么。 Bytearray铸造导致:
File "image_upload.py", line 1621, in store_image
s1.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 710, in commit
self.transaction.commit()
[ ... the same as above ... ]
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/default.py", line 331, in do_execute
cursor.execute(statement, parameters)
TypeError: can't escape Part to binary
File "image_upload.py", line 1611, in store_image
image_entry['thumbnail'] = bytearray(thumb.copy())
TypeError: iteration over non-sequence
缓冲区强制转换导致:
File "image_upload.py", line 1621, in store_image
s1.commit()
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/orm/session.py", line 710, in commit
self.transaction.commit()
[ ... the same as above ... ]
File "/usr/local/lib/python2.7/dist-packages/SQLAlchemy-0.7.10-py2.7-linux-x86_64.egg/sqlalchemy/engine/default.py", line 331, in do_execute
cursor.execute(statement, parameters)
TypeError: can't escape Part to binary
File "image_upload.py", line 1611, in store_image
image_entry['thumbnail'] = bytearray(thumb.copy())
TypeError: iteration over non-sequence
在这里没有找到答案:-()
- 是否有更好的工具/库用于此?
只创建缩略图的人 编辑1: 我对如何将图像对象保存到流做了一些研究。
但首先我尝试了PIL.Image.tostring()函数:
File "image_upload.py", line 1611, in store_image
image_entry['thumbnail'] = buffer(thumb.copy())
TypeError: buffer object expected
然后我尝试了BytesIO()模块。它导致不支持操作:fileno PIL
因为这是PIL中的一个已知错误,我用它的叉形枕头替换了PIL,并再次尝试:
thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
thumb.tostring()
image_entry['thumbnail'] = thumb.copy()
两者都给了我SQLAlchemy类型错误:无法将实例转义为二进制当然,就像之前错误被追溯到:
thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
stream = BytesIO()
thumb.save(stream, "JPEG")
image_entry['thumbnail'] = stream.getvalue()
最后我用StringIO.StringIO()替换了tesio(),但它没有改变任何事情。我想这更像是一个特殊的炼金术问题 编辑2: 在我错误地提到未知的SQLAlchemy类型错误之前:无法将部分转义为二进制
在编辑1中更正,这是SQLAlchemy类型错误:无法将实例转义为二进制
这只是因为我试图将发布的值保存到数据库中:
s1.add(ObjectImage(**image_entry))
s1.commit() #line 1621
编辑3:
似乎我犯了一个错误,仍然试图插入完整大小的图像作为实例,而缩略图已经以正确的方式“格式化”
"""
The variable "image_file"
comes directly from the POSTed dictionary.
image_file = kwargs['image_file']
Alternative first line:
img = StringIO.StringIO(image_file.file.read())
"""
img = BytesIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image_file # the dict value was meant be image.copy()
s1.add(ObjectImage(**image_entry))
s1.commit() #line 1621
现在表中至少插入了一个很长的十六进制代码,也许我可以使用它。但是,图像和缩略图列似乎包含相同的十六进制代码 编辑4: 图像和缩略图不包含相同的十六进制代码,稍后确认为SQL查询。
只有前1179个字符和后4个字符是相同的,我刚在开头检查过。
两者之间的内容不同,每个条目的长度也不同。
最后,将整个代码段作为一个代码段 首先是必要的进口:
"""
old version:
"""
img = BytesIO(image_file.file.read())
image = Image.open(img)
image_entry['image'] = image.copy()
"""
new version:
"""
img = BytesIO(image_file.file.read())
image = Image.open(img)
fullsize = image.copy()
stream = BytesIO()
fullsize.save(stream, "JPEG")
image_entry['image'] = stream.getvalue()
"""
from EDIT 1:
"""
thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
stream = BytesIO()
thumb.save(stream, "JPEG")
image_entry['thumbnail'] = stream.getvalue()
第二个引擎和会话:
from io import BytesIO
import base64
import cherrypy
import sqlalchemy
from sqlalchemy.orm import sessionmaker
from PIL import Image
第三,图像和缩略图上传代码:
pg = sqlalchemy.create_engine(
'postgresql://{}:{}@{}:{}/{}'.format(
user, password, server, port, data))
Session = sessionmaker(bind=pg)
cherrypy.session['session'] = Session
最后是一个简短的HTML缩略图检索代码:
s1 = cherrypy.session.get('session')
image_file = kwargs['image_file']
img = BytesIO(image_file.file.read())
image = Image.open(img)
fullsize = image.copy()
stream = BytesIO()
fullsize.save(stream, "JPEG")
image_entry['image'] = stream.getvalue()
thumb = image.copy()
thumb.thumbnail((30000, 300,), Image.ANTIALIAS)
stream = BytesIO()
thumb.save(stream, "JPEG")
image_entry['thumbnail'] = stream.getvalue()
image_entry['sample'] = chosen_one
image_entry['filename'] = image_file.filename
image_entry['preview'] = 't'
s1.add(ObjectImage(**image_entry))
s1.commit() #line 1621
s1=cherrypy.session.get('session'))
qry=(s1.query(ObjectImage.id、ObjectImage.filename、ObjectImage.缩略图)。
过滤器(ObjectImage.preview=='t'))
对于qry中的rowX:
收益率(u“”。
格式(base64.b64encode(rowX.缩略图)))
出于性能原因,我考虑编写一个额外的函数来替换数据URI方案。但现在要感谢Neaţu Ovidiu Gabriel提到“保存到流”选项,
感谢提供这些资源的人们: -(简单io.BytesIO()示例)
-(提到不支持的操作:fileno)我不知道Cherrypy,但我猜您正在将一个PIL.Image对象作为参数发送到s1,而s1无法执行它必须执行的操作,因为他无法识别此类对象。没错!这就是为什么我需要一种方法将PIL.Image对象转换成更有用的东西。你不知道这方面有什么建议吗?根据,s1是到PostgreSQL数据库的SQLAlchemy连接。我会在我的帖子中编辑这个。你可以试试PIL.Image.save(…)。保存(..)的外观:保存(self,fp,format=None,**参数)。说明:将图像保存到文件或流。您应该尝试使用流-我认为如果您不想保存到磁盘,这就是您想要的。