跳转到主要内容

使用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 (40.9 kB 查看散列)

上传时间

由支持