使用Blob支持的ZODB文件和图像 -- Zope 3内容组件
项目描述
Blob文件
本包提供了一个zope.app.file.interfaces.IFile的实现,该实现使用了ZODB 3.8中引入的Blob支持。其主要目的是为现有实例提供一个简单的迁移路径。有关更高级的文件实现,请参阅zope.file和z3c.extfile。
zope.app.file中的标准实现使用块对象将大文件分割成可管理的部分。这些块在服务器缓存中流动,而blobs则直接由发布者消耗。这种blob实现与旧的zope.app.file实现之间的主要区别在于用Blob替换了块对象。
详细文档
Blob文件实现
此zope.app.file.interfaces.IFile的实现利用了新的ZODB blob支持,并试图与zope.app.file中的现有文件实现完全向后兼容。
与zope.app.file.File的兼容性
以下测试与zope.app.file包的测试完全一致。
让我们测试构造函数
>>> from zope.app.file import File, Image>>> file = File() >>> file.contentType '' >>> file.data ''>>> file = File('Foobar') >>> file.contentType '' >>> file.data 'Foobar'>>> file = File('Foobar', 'text/plain') >>> file.contentType 'text/plain' >>> file.data 'Foobar'>>> file = File(data='Foobar', contentType='text/plain') >>> file.contentType 'text/plain' >>> file.data 'Foobar'
让我们测试可变函数
>>> file = File() >>> file.contentType = 'text/plain' >>> file.contentType 'text/plain'>>> file.data = 'Foobar' >>> file.data 'Foobar'>>> file.data = None Traceback (most recent call last): ... TypeError: Cannot set None data on a file.
让我们测试大量数据输入
>>> file = File()
以字符串形式插入
>>> file.data = 'Foobar'*60000 >>> file.getSize() 360000 >>> file.data == 'Foobar'*60000 True
以FileChunk形式插入数据
>>> from zope.app.file.file import FileChunk >>> fc = FileChunk('Foobar'*4000) >>> file.data = fc >>> file.getSize() 24000 >>> file.data == 'Foobar'*4000 True
从文件对象中插入数据
>>> import cStringIO >>> sio = cStringIO.StringIO() >>> sio.write('Foobar'*100000) >>> sio.seek(0) >>> file.data = sio >>> file.getSize() 600000 >>> file.data == 'Foobar'*100000 True
最后,但同样重要的是,验证接口
>>> from zope.interface.verify import verifyClass >>> zope.app.file.interfaces.IFile.implementedBy(File) True >>> verifyClass(zope.app.file.interfaces.IFile, File) True
文件表示适配器测试
>>> from zope.app.file.file import FileReadFile >>> file = File() >>> content = "This is some file\\ncontent." >>> file.data = content >>> file.contentType = "text/plain" >>> FileReadFile(file).read() == content True >>> FileReadFile(file).size() == len(content) True>>> from zope.app.file.file import FileWriteFile >>> file = File() >>> content = "This is some file\\ncontent." >>> FileWriteFile(file).write(content) >>> file.data == content True
现有文件的发展
请注意,以下代码是实验性的。在经过仔细测试之前,不应在生产环境中使用此代码。如果您想替换现有的zope.app.file.File实例,请备份您的Data.fs并在configure.zcml中取消以下行的注释。
- <utility
component=”.generations.BlobFileSchemaManager” name=”z3c.blobfile” />
假设您已经有一个包含zope.app.file内容类型的现有数据库
>>> from z3c.blobfile import testing >>> root = getRootFolder()>>> root[u'file'] = File('A text file', contentType='text/plain') >>> root[u'image'] = Image(testing.zptlogo)
由于evolve步骤寻找IFile的实现,我们必须提供一种方法来识别除了zope.app.file.File和Image之外的其他实现。让我们添加一个无意义的实现作为示例
>>> root[u'custom'] = testing.MyFile()
请注意,我们无法假设这些对象是孤立存在的。其中许多对象可能被注释、索引,甚至可能被注册为实用程序等。当对象被替换时,evolution步骤会抛出标准事件,而应用程序需要相应地识别这些替换。如果您的应用程序有特殊需求,您可以订阅FileReplacedEvent。
由于这很大程度上取决于应用程序,我们不会测试所有与其他对象的关联。在这里,我们仅以ZopeDublinCore时间戳为例,说明我们的evolve步骤尽可能地保留尽可能多的内容。
>>> from zope.dublincore.interfaces import IZopeDublinCore >>> import datetime>>> IZopeDublinCore(root[u'file']).created = datetime.datetime.utcnow() >>> t1 = IZopeDublinCore(root[u'file']).created >>> IZopeDublinCore(root[u'file']).title = u'No evolution'
现在我们执行基本的evolve步骤。由于我们预计会有一些警告日志,我们需要
>>> from zope.testing.loggingsupport import InstalledHandler >>> import logging >>> log_handler = InstalledHandler('z3c.blobfile.generations')>>> from z3c.blobfile.generations.evolve1 import evolveZopeAppFile >>> evolveZopeAppFile(root) >>> transaction.commit()>>> for record in log_handler.records: ... print record.getMessage() Unknown ...interfaces.IFile implementation z3c.blobfile.testing.MyFile
evolve步骤之后,类类型已更改为z3c.blobfile实现
>>> import z3c.blobfile >>> isinstance(root[u'file'], z3c.blobfile.file.File) True >>> isinstance(root[u'image'], z3c.blobfile.image.Image) True
只有自定义实现保持不变
>>> isinstance(root[u'custom'], testing.MyFile) True
文件数据保持不变……
>>> root[u'file'].data 'A text file' >>> root[u'file'].contentType 'text/plain'>>> root[u'image'].data == testing.zptlogo True
注释也如此
>>> IZopeDublinCore(root[u'file']).created == t1 True >>> IZopeDublinCore(root[u'file']).title u'No evolution'
甚至实现细节,如_data属性,仍然有效
>>> root[u'file']._data 'A text file'
复制
让我们检查blob文件是否可以成功复制。此功能需要新的“zope.copy”包以及使用zope.copy的zope.copypastemove版本(>=3.5.1)。
>>> from zope.copy import copy >>> file = z3c.blobfile.file.File() >>> file.data = u'hello, world' >>> image = z3c.blobfile.file.File() >>> image.data = 'some image bytes' >>> transaction.commit()>>> file_copy = copy(file) >>> file_copy.data == file.data True>>> image_copy = copy(image) >>> image_copy.data == image.data True
更改
0.1.5 (2011-02-11)
对读取的信息字节数设置上限(64k),并一次性读取这些字节。
错误:正确检测JPEG图像的尺寸,该尺寸在IMAGE_INFO_BYTES位置之后。
使测试与ZODB 3.9兼容。
0.1.4 (2009-03-03)
为zope.copy添加复制钩子,以修复blob文件/图像的复制。
将包的邮件列表地址更改为zope-dev at zope.org,而不是已退役的zope3-dev。
0.1.3 (2008-10-20)
错误:在Image初始化时不要两次获取/设置图像数据。
缓存文件大小,并在写入访问时使它无效。
使用新的openDetached方法下载文件/图像,该方法提供对blob的只读文件类似访问,与数据库连接分离。
0.1.2 (2008-09-11)
错误:在“overrides.zcml”中将i18n域设置为避免警告。
不要在添加/上传表单中暴露Blob实现细节。另外,“zope”翻译域没有“上传文件(Blob)”的翻译,只有“上传文件”的翻译,所以使用它。
0.1.1 (2008-09-08)
错误:将zope.app.wsgi.fileresult.FileResult注册为BlobFile的适配器,使优化文件视图真正工作。
错误:也为z3c.blobfile.image.Image使用优化文件视图。
错误:使文件和图像的blob版本分别实现IBlobFile和IBlobImage接口。这启用了z3c.blobfile的视图。
错误:使用本地ZopeMessageFactory。这修复了Zope 2.10上的导入错误
0.1.0 (2008-02-27)
初始版本
项目详情
z3c.blobfile-0.1.5.zip的散列
算法 | 散列摘要 | |
---|---|---|
SHA256 | f1695da9de4eaf241a8214c8cf8663d85d1de11b8ea9f552b4398d449ec65353 |
|
MD5 | 2e806640aa2f3b51e4578f35c44f567a |
|
BLAKE2b-256 | 8f4446d7f7592d42c76be006184af6a7f21fe713d9020a0335e42a11b8a77bb6 |