图像、文件和带有文件名的blob文件类型和字段
项目描述
简介
此包包含用于存储的字段和包装对象:
带有文件名的文件
带有文件名的图像
提供了基于Blob和非基于Blob的类型。基于Blob的类型需要ZODB3包的版本为3.8.1或更高版本,并在zope.conf中配置BLOB。
注册了plone.supermodel处理器。
有关更多详细信息,请参阅usage.rst doctest。
源代码
注意:此包根据BSD许可证授权。请勿添加对GPL代码的依赖!
贡献者请阅读文档Plone核心开发的流程
源代码位于托管在GitHub上的Plone代码仓库。
变更日志
6.3.1 (2024-07-30)
错误修复
修复:上传未设置宽度和高度的svg @dobri1408 (#161)
6.3.0 (2024-03-15)
新功能
改进对未注册但常见的类型的内容类型检测逻辑。
更改get_contenttype以支持未注册或未注册的IANA的常见类型,如image/webp或audio/midi。
注意:image/webp已经是一个IANA注册的类型,并且也已由Products.MimetypesRegistry添加。[thet] (157-2)
支持允许的媒体类型。
支持将文件限制为特定媒体类型,通过在文件和图像字段上设置“accept”属性,就像HTML文件输入的“accept”属性一样。
修复:#157 [thet] (#157)
6.2.3 (2023-11-03)
错误修复
在检查mimetype是否允许内联显示时更加严格。[maurits] (#1167)
6.2.2 (2023-10-18)
错误修复
修复文件修改时间的计算。@davisagli (#153)
6.2.1 (2023-09-21)
错误修复
修复存储的XSS(跨站脚本)问题,针对SVG图像。通过强制下载而不是内联显示来解决。请参阅安全公告。[maurits] (#1)
6.2.0 (2023-09-14)
新功能
添加内部修改时间戳,并提供对_p_mtime的回退。[mathias.leimgruber] (#149)
将新的内部修改时间戳用作缩放哈希键的一部分。[mathias.leimgruber] (#150)
6.1.2 (2023-08-31)
错误修复
修复了包含大量元数据的SVG图像无法正确显示的问题(导致宽度和高度为1px)。当
修复了问题问题147。[mliebischer] (#147)
6.1.1 (2023-06-22)
错误修复
如果发布时不包含子路径,则返回400 Bad Request响应。@@images视图。[davisagli] (#144)
测试
修复测试以与各种beautifulsoup4版本一起工作。[maurits] (#867)
6.1.0 (2023-05-22)
新功能
将Zope2FileUploadStorable代码从plone.app.z3cform移动到这里,以解决循环依赖。[gforcada] (#3764)
6.0.2 (2023-05-08)
错误修复
修复使用原始图像而不是缩放时的图片标签。[maurits] (#142)
6.0.1 (2023-03-14)
测试
Tox:显式测试
plone.namedfile
包。[maurits] (#50)
6.0.0 (2022-11-22)
错误修复
当找不到图片变体的缩放比例时记录警告。直到现在,这会导致异常。[maurits] (#134)
防止匿名用户首次加载包含私有图片的页面时抛出异常。匿名用户在加载图片时仍然会收到未授权访问,这是预期的。HTML至少可以正常显示。修复了问题135。[maurits] (#135)
修复了每次请求原始图片时都写入数据库的问题。这发生在请求具有唯一ID的原始图片时。[maurits] (#3678)
6.0.0b5 (2022-10-03)
破坏性更改
不再在3.6上测试Plone 5.2,在3.7上测试Plone 6.0。[maurits] (#3637)
错误修复
使用
mode
参数代替已废弃的direction
,并向用户发出警告。[petschki, maurits] (#102)
6.0.0b4 (2022-09-07)
错误修复
将
getAllowedSizes
和getQuality
从CMFPlone.utils移动到本包。[jensens] (#132)
6.0.0b3 (2022-07-20)
错误修复
从ImageScale类获取标题。当上下文是瓦片时,防止跟踪异常。如果没有找到标题,则回退到空字符串。[maurits] (#128)
6.0.0b2 (2022-06-27)
错误修复
不要在
image_scales
字典中使用完整URL。[petschki] (#123)
6.0.0b1 (2022-06-23)
新功能
创建标签不再生成实际的缩放。[maurits] (#113)
将图片方法添加到ImageScaling中,并将其包含在@@image-test中。图片标签仅在Plone 6上工作,其他几个分支合并了图片变体。请参阅plip-image-srcsets.cfg。如果不可用(如Plone 5.2),则创建一个普通的图片标签。[MrTango] (#113)
为编辑器添加
@@images-test
页面。这显示当前上下文图片字段的多个变体。它显示存储的缩放列表。它允许清除存储的缩放。[maurits] (#113)移除标记请求禁用CSRF保护(需要plone.scale与https://github.com/plone/plone.scale/pull/58)[mamico] (#177)
正确使用属性
_sizes
进行本地缓存,确保可用_sizes [mamico] (#177)仅在缺失时向缩放存储添加额外信息 [mamico] (#177)
将图像字段适配器注册到新的image_scales元数据。在图像缩放视图中使用此适配器从脑图列表中获取图像。此代码在Plone 5上不活动,仅在Plone 6上。[cekk, maurits] (#3521)
错误修复
清理:isort,black,pyupgrade,移除six的使用等。[maurits] (#120)
6.0.0a4 (2022-05-26)
错误修复
仅检查宽度以确定HiDPI图像是否会比原始图像大。否则,当缩放定义的高度为65536时,永远不会包含HiDPI srcsets。[maurits] (#114)
修复了即使作为管理员访问私有图片的
@@images/image
时的未授权访问问题。修复了先前版本中引入的问题。[maurits] (#118)
6.0.0a3 (2022-02-28)
错误修复
ImageScaling
视图:使用guarded_orig_image
从URL获取字段。这主要使得视图更容易自定义。[maurits] (#104)
6.0.0a2 (2022-02-23)
破坏性更改
从setup.py中删除了已废弃的额外功能。这些功能现在已删除:
blobs
,editor
,marshaler
,scales
,supermodel
。请参阅问题106。[maurits] (#106)
新功能
将
AnnotationStorage
注册为IImageScaleStorage
多适配器。两者均来自plone.scale
。在我们存储或获取图像缩放时使用此适配器。[maurits] (#44)
6.0.0a1 (2022-01-28)
破坏性更改
停止对Python 2.7的支持。主要目标是Plone 6,但我们尝试使其在Plone 5.2上运行,使用Python 3。请参阅plone.scale问题44中的讨论。[maurits] (#44)
错误修复
修复Python 3上的NameError file。使用io.IOBase代替。(#3)
5.6.0 (2021-12-29)
新功能
使DefaultImageScalingFactory更灵活,具有您可以重写的函数。[maurits] (#104)
5.5.1 (2021-07-28)
错误修复
强烈缓存稳定的图像缩放。当plone.app.imaging可用时,这已经完成。否则,我们应该自己这样做。修复问题100。[maurits] (#100)
5.5.0 (2021-06-30)
新功能
防止存储的XSS攻击(svg、html)。通过实现可信mimetypes的允许列表来完成此操作。您可以通过仅使用svg、html和javascript的拒绝列表来反转此操作。通过设置OS环境变量NAMEDFILE_USE_DENYLIST=1来完成此操作。来自Products.PloneHotfix20210518。[maurits] (#3274)
5.4.0 (2020-06-23)
新功能
范围支持(https://mdn.org.cn/en-US/docs/Web/HTTP/Range_requests)[mamico] (#86)
5.3.1 (2020-04-30)
错误修复
修复图像缩放,以便在不需要缩放时重用原始图像,允许Plone REST API在无需性能损失的情况下使用缓存的可缩放URL。[datakurre] (#92)
5.3.0 (2020-04-21)
新功能
将使用字段值_p_mtime而不是上下文对象_p_mtime作为图像缩放无效化时间戳,以修复上下文对象(例如,具有主图像的文档)修改会使其所有图像字段缩放无效,即使图像本身未修改的问题。[datakurre] (#91)
5.2.2 (2020-04-14)
错误修复
在DefaultImageScalingFactory中关闭BlobFile。[timo] (#89)
在将文件传递给Pillow之前处理SVG文件,修复#3063 [sneridagh] (#3063)
5.2.1 (2019-12-11)
错误修复
修复tiff支持。删除process_tiff并让PIL完成工作。[mamico] (#85)
当使用PIL时修复getImageInfo中的content_type。[mamicp] (#85)
5.2.0 (2019-11-25)
新功能
加载SVG文件。[balavec] (#63)
5.1.0 (2019-10-21)
新功能
添加新的接口plone.namedfile.interfaces.IPluggableFileFieldValidation和plone.namedfile.interfaces.IPluggableImageFieldValidation。重构:现在字段验证现在寻找具有此接口的适配器,该接口适配字段和值。所有找到的适配器都被调用。图像内容类型检查器(之前存在)现在是迄今为止唯一实现和注册的适配器。其他适配器可以在相关或自定义代码中注册。[jensens] (#81)
5.0.5 (2019-10-12)
错误修复
修复未关闭文件的ResourceWarnings [mamico] (#80)
5.0.4 (2019-06-27)
错误修复
现在可以更容易地自定义@@images视图。[ale-rt] (#65)
5.0.3 (2019-04-29)
错误修复
增加静态MAX_INFO_BYTES以修复无法正确从具有大量元数据的图像中提取文件大小的问题。[elioschmutz] (#74)
5.0.2 (2018-11-13)
错误修复
当Exif数据不良时,不要使图像上传失败。[maurits] (#68)
5.0.1 (2018-11-08)
错误修复
修复对BytesIO的一个遗忘的更改。[pbauer]
5.0 (2018-11-02)
新功能
针对Zope 4(仅测试更改)。
Python 3兼容性 [pbauer, matthewwilkes, fgrcon, jensens]
错误修复
为Python 2/3兼容性做准备 [ale-rt, pbauer, MatthewWilkes, jensens]
删除对“retina”的提及(https://github.com/plone/Products.CMFPlone/issues/2123)[tkimnguyen]
修复测试以使用新的zope testbrowser内部。[davisagli]
4.2.3 (2017-09-08)
错误修复
修复#56号错误,其中在未给定宽度或高度且未提供缩放时,srcset生成失败。https://github.com/plone/plone.namedfile/pull/56 [jensens]
4.2.2 (2017-07-03)
错误修复
如果由于任何原因,字段名在上下文中不可用,则不要破坏DefaultImageScalingFactory。[thet]
为不同的域使用不同的缓存键。[mamico]
4.2.1 (2017-05-30)
错误修复
修复#46号错误,当process_png、process_jpeg和process_tiff失败时,会出现“在赋值之前引用宽度”错误。[thet]
修复contentType属性应为str类型的问题,导致验证错误(修复了#38)。[rodfersou]
修复了在ImageIFD.XResolution或ImageIFD.YResolution未设置时图像旋转的bug。[loechel]
修复:不要将失败的PIL图像识别记录为错误,而是记录为警告。[jensens]
修复:重新添加了与Plone 4的兼容性。[loechel]
4.2.0 (2017-03-26)
新功能
使用srcset属性添加视网膜图像缩放。[didrix]
4.1.2 (2017-02-12)
错误修复
BrowserViews没有Acquisition。[pbauer]
4.1.1 (2017-01-20)
新功能
添加基于EXIF数据的自动图像旋转,适用于所有图像。基于piexif库和maartenkling以及ezvirtual的思路。选择piexif是因为它允许读取和写入EXIF数据以供未来增强。请参阅http://piexif.readthedocs.org/en/latest/关于Orientation示例和描述,请参阅http://www.daveperrett.com/articles/2012/07/28/exif-orientation-handling-is-a-ghetto/测试数据https://github.com/recurser/exif-orientation-examples具有不同MIME类型(JPEG和TIFF)的附加测试图像以及可能的问题:https://github.com/ianare/exif-samples.git [loechel]
支持SVG图像 [tomgross]
错误修复
在getImageInfo中添加了对Tiff图像的处理。[loechel]
重构包。将图像元数据检测移至自己的子文件夹中 [loechel]
4.1 (2016-09-14)
新功能
添加Pdata存储 [vangheem]
4.0 (2016-08-12)
不兼容性
仅针对Plone 5.1,coredev 5.0和4.3位于3.0.x分支 [jensens]
plone.supermodel、plone.scale和plone.schemaeditor现在是硬依赖。由于bbb原因,setup.py中的额外部分被保留,但为空。条件代码现在不再条件化。这大大简化了代码。
zope.app.file不再是硬依赖。如果存在,则仍会检查其FileChunk实现,否则不会。
新功能
使用适配器作为缩放工厂,类似于plone.scale>=1.5中的适配器 [jensens]
修复
由于二进制文件以文本模式打开而导致Windows 10上的几个测试失败。已修复。[smcmahon]
防止从与未提交的blob关联的临时文件创建文件流迭代器。通过尝试删除或访问另一个进程正在使用的文件来修复Windows 10上的“WindowsError 32”错误。[smcmahon]
修复测试以与最新的plone.scale更改兼容,其中gif图像不再转换为jpeg。[thet]
修复了测试设置以正确使用层。[jensens]
修复了test_blobfile.py中的测试隔离问题。[jensens]
修复了测试.zcml中缺少i18n:domain的警告。[gforcada]
修复了一些代码分析警告。[gforcada]
3.0.8 (2016-02-26)
修复
遵循PEP 8、UTF-8标题、实现/适配装饰器、doctest格式。[thet, jensens]
对getImageSize方法进行工作区处理。防止返回(-1, -1)作为图像的大小。[andreesg]
3.0.7 (2016-02-12)
修复
将plone.protect作为软依赖。这允许在不使用Plone堆栈的设置中使用此包。修复了plone/Products.CMFPlone#1311 [thet]
3.0.6 (2016-01-08)
修复
稳定测试。[gotcha]
3.0.5 (2015-11-26)
新功能
将webdav支持添加到图像缩放中。https://github.com/plone/Products.CMFPlone/issues/1251 [maurits]
3.0.4 (2015-10-28)
修复
不再依赖于已弃用的bobobase_modification_time from Persistence.Persistent。[thet]
3.0.3 (2015-08-14)
当scale返回None时,访问@@images视图中的tag方法不会失败。[thet]
3.0.2 (2015-03-13)
当通过基于UID的URL访问图像缩放时,使用plone.stableResource规则集缓存图像缩放。(需要plone.app.imaging >= 1.1.0)[davisagli]
3.0.1 (2014-10-23)
修复了在Content-Disposition标题中插入文件名的问题。[kroman0]
在下载视图中也要尊重字段级别的安全性,包括主字段。[jensens]
国际化字段工厂标签。[thomasdesvenain]
3.0.0 (2014-04-13)
创建比例时禁用CSRF保护,这样我们就可以写入数据库。[vangheem]
2.0.5 (2014-02-19)
确保在文件包中使用之前创建zope.app.file.file模块别名。[thomasdesvenain]
2.0.4 (2014-01-27)
创建比例时禁用CSRF保护,这样我们就可以写入数据库。[vangheem]
验证图像字段:使用MIME类型检查内容是否实际上是图像。[thomasdesvenain]
修复:当contentType为空字符串时,get_contenttype仍然可以工作。
NamedFile与zope.app.file FileChunk的向后兼容性。避免NamedFile验证意外失败。[thomasdesvenain]
2.0.5 (2014-02-19)
确保在文件包中使用之前创建zope.app.file.file模块别名。[thomasdesvenain]
2.0.4 (2014-01-27)
NamedFile与zope.app.file FileChunk的向后兼容性。避免NamedFile验证意外失败。[thomasdesvenain]
验证图像字段:使用MIME类型检查内容是否实际上是图像。[thomasdesvenain]
修复:当contentType为空字符串时,get_contenttype仍然可以工作。[thomasdesvenain]
2.0.3 (2013-12-07)
缩放遍历器现在不再尝试在一次遍历中走两步。这在chameleon中是不可能的。[do3cc]
2.0.2 (2013-05-23)
如果存在,则使用plone.app.imaging的(>=1.0.8)质量设置。https://dev.plone.org/ticket/13337 [khink]
修复在未实现Dublin Core的上下文中无效化的错误;特别是portlet分配。回退为bobo_modification_time。也许portlet分配应该实现modified()?[tmog]
修复了在Plone 4.3迁移后出现的问题,即处理TTW Dexterity内容类型图像字段数据时,如果图像数据很大并以zope.app.file.file.FileChunk的形式存储在ZODB中而不是原始字符串数据。[miohtama]
2.0.1 (2013-01-17)
在缩放中添加方向参数支持(在标签和缩放函数中曾忽略)。现在,使用参数direction=’down’调用标签函数裁剪图像。默认方向为’tumbnail’,因此默认行为保持不变。[jriboux]
2.0 (2012-08-29)
将文件和图像值实现移到这里,而不是扩展来自zope.app.file和z3c.blobfile的实现。这有助于解决依赖关系混乱的问题。[davisagli]
基于blob的文件和图像实现现在总是可用。(但只有在Zope使用支持blob的存储时它们才会工作。)[davisagli]
为@@images视图添加对HEAD请求的支持。[anthonygerrard]
为文件下载视图的子类添加覆盖头部信息的钩子。[anthonygerrard]
如果文件名包含非ASCII字符,则不要在头部设置文件名。[do3cc]
如果jpeg文件包含损坏的元数据,则添加Dexterity Image会导致TypeError。关闭http://dev.plone.org/ticket/12753。[由joka补丁,kleist应用]
1.0.6 - 2011-10-18
修复测试失败。[davisagli]
修复在具有Unicode标题的项目上生成缩放标签时的错误。[tomster]
1.0.5 - 2011-09-24
使下载视图尊重要下载的字段的自定义读取权限,而不仅仅是检查对象的整体视图权限。[davisagli]
1.0.4 - 2011-08-21
修复在具有非ASCII字符标题的项目上生成缩放标签时的错误。[davisagli]
确保在不允许的容器上可以访问允许的属性上的图像缩放。[davisagli]
为safe_filename添加单元测试,因为在这个模块中没有进行练习。(应该移动到plone.formwidget.namedfile?)[lentinj]
1.0.3 - 2011-05-20
1.0.2 - 2011-05-19
不要从ImageScale标签中省略空字符串属性。[elro]
1.0.1 - 2011-05-19
在ImageScale的tag方法中允许省略height/width/alt/title,当它们作为None参数提供时。[elro]
在打包的文件字段中,根据RFC 2231对Content-Disposition头中的filename参数进行编码。这确保了具有非ASCII字符的文件名可以成功解包。[davisagli]
使各种文件类仅接受Unicode文件名。[davisagli]
1.0 - 2011-04-30
使用唯一的URL访问原始缩放。[elro]
避免对图像缩放使用Content-Disposition。[elro]
1.0b8 - 2011-04-12
声明对plone.rfc822 >= 1.0b2的依赖(用于IPrimaryField)。[davisagli]
添加一个不设置Content-Disposition的@@display-file视图,例如,这样我们就不强制下载图片。[lentinj]
1.0b7 - 2011-03-22
支持以缩放比例获取原始大小。[elro]
将tag()方法添加到缩放视图中。[elro]
缩放:引用额外标签属性的值。[elro]
1.0b6 - 2011-02-11
将主字段支持添加到@@download和@@images视图中。[elro]
将getAvailableSizes和getImageSize添加到@@images视图中。[elro]
1.0b5 - 2010-04-19
添加对缩放图像的支持。有关详细信息,请参阅usage.txt。[davisagli]
修复字段架构,以便可以使用plone.schemaeditor添加字段。[rossp]
1.0b4 - 2009-11-17
避免使用内部_current_filename()辅助函数,该函数在ZODB 3.9中已消失。[optilude]
为plone.schemaeditor添加字段工厂(只有当plone.schemaeditor可用时安装)[davisagli]
1.0b3 - 2009-10-08
添加plone.rfc822字段编解码器(只有当plone.rfc822可用时安装)[optilude]
1.0b2 - 2009-09-17
添加plone.supermodel导入/导出处理器(只有当plone.supermodel可用时安装)。[optilude]
1.0b1 - 2009-05-30
将z3c.blobfile(以及通用blob)作为软依赖。您需要单独依赖z3c.blobfile(并且可能将其锁定到版本0.1.2),以获取NamedBlobFile和NamedBlobImage字段。这意味着plone.namedfile可以与不支持BLOB的ZODB版本一起使用。此策略可能会在2.0版本中重新审视。[optilude]
1.0a1 - 2009-04-17
初始发布
用法
此示例演示了如何使用该软件包。
架构字段
以下架构字段可以用来描述文件数据。如果安装了z3c.blobfile,我们只会测试字段的BLOB版本
>>> from zope.interface import Interface >>> from plone.namedfile import field >>> class IFileContainer(Interface): ... simple = field.NamedFile(title=u"Named file") ... image = field.NamedImage(title=u"Named image file") ... blob = field.NamedBlobFile(title=u"Named blob file") ... blobimage = field.NamedBlobImage(title=u"Named blob image file")
以下存储数据,类型如下
>>> from zope.interface import implementer >>> from plone import namedfile >>> @implementer(IFileContainer) ... class FileContainer(object): ... __allow_access_to_unprotected_subobjects__ = 1 ... def __init__(self): ... self.simple = namedfile.NamedFile() ... self.image = namedfile.NamedImage() ... self.blob = namedfile.NamedBlobFile() ... self.blobimage = namedfile.NamedBlobImage()
文件数据和内容类型
现在让我们展示如何获取和设置文件数据。
FileContainer类最初创建空对象
>>> container = FileContainer() >>> bytearray(container.simple.data) bytearray(b'') >>> container.simple.contentType '' >>> container.simple.filename is None True >>> len(container.image.data) 0 >>> container.image.contentType '' >>> container.image.filename is None True >>> len(container.blob.data) 0 >>> container.blob.contentType '' >>> container.blob.filename is None True >>> len(container.blobimage.data) 0 >>> container.blobimage.contentType '' >>> container.blobimage.filename is None True
现在让我们在这些文件中设置一些实际数据。注意,构造函数将尝试根据文件扩展名猜测文件名
>>> container.simple = namedfile.NamedFile('dummy test data', filename=u"test.txt") >>> bytearray(container.simple.data) bytearray(b'dummy test data') >>> container.simple.contentType 'text/plain' >>> print(container.simple.filename) test.txt >>> container.blob = namedfile.NamedBlobFile('dummy test data', filename=u"test.txt") >>> bytearray(container.blob.data) bytearray(b'dummy test data') >>> container.blob.contentType 'text/plain' >>> print(container.blob.filename) test.txt
让我们也尝试读取一个GIF,这是由zope.app.file测试提供的
>>> zptlogo = ( ... b'GIF89a\x10\x00\x10\x00\xd5\x00\x00\xff\xff\xff\xff\xff\xfe\xfc\xfd\xfd' ... b'\xfa\xfb\xfc\xf7\xf9\xfa\xf5\xf8\xf9\xf3\xf6\xf8\xf2\xf5\xf7\xf0\xf4\xf6' ... b'\xeb\xf1\xf3\xe5\xed\xef\xde\xe8\xeb\xdc\xe6\xea\xd9\xe4\xe8\xd7\xe2\xe6' ... b'\xd2\xdf\xe3\xd0\xdd\xe3\xcd\xdc\xe1\xcb\xda\xdf\xc9\xd9\xdf\xc8\xd8\xdd' ... b'\xc6\xd7\xdc\xc4\xd6\xdc\xc3\xd4\xda\xc2\xd3\xd9\xc1\xd3\xd9\xc0\xd2\xd9' ... b'\xbd\xd1\xd8\xbd\xd0\xd7\xbc\xcf\xd7\xbb\xcf\xd6\xbb\xce\xd5\xb9\xcd\xd4' ... b'\xb6\xcc\xd4\xb6\xcb\xd3\xb5\xcb\xd2\xb4\xca\xd1\xb2\xc8\xd0\xb1\xc7\xd0' ... b'\xb0\xc7\xcf\xaf\xc6\xce\xae\xc4\xce\xad\xc4\xcd\xab\xc3\xcc\xa9\xc2\xcb' ... b'\xa8\xc1\xca\xa6\xc0\xc9\xa4\xbe\xc8\xa2\xbd\xc7\xa0\xbb\xc5\x9e\xba\xc4' ... b'\x9b\xbf\xcc\x98\xb6\xc1\x8d\xae\xbaFgs\x00\x00\x00\x00\x00\x00\x00\x00' ... b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' ... b'\x00,\x00\x00\x00\x00\x10\x00\x10\x00\x00\x06z@\x80pH,\x12k\xc8$\xd2f\x04' ... b'\xd4\x84\x01\x01\xe1\xf0d\x16\x9f\x80A\x01\x91\xc0ZmL\xb0\xcd\x00V\xd4' ... b'\xc4a\x87z\xed\xb0-\x1a\xb3\xb8\x95\xbdf8\x1e\x11\xca,MoC$\x15\x18{' ... b'\x006}m\x13\x16\x1a\x1f\x83\x85}6\x17\x1b $\x83\x00\x86\x19\x1d!%)\x8c' ... b'\x866#\'+.\x8ca`\x1c`(,/1\x94B5\x19\x1e"&*-024\xacNq\xba\xbb\xb8h\xbeb' ... b'\x00A\x00;' ... ) >>> container.image = namedfile.NamedImage(zptlogo, filename=u"zpt.gif") >>> container.image.data == zptlogo True >>> container.image.contentType 'image/gif' >>> print(container.image.filename) zpt.gif >>> container.blobimage = namedfile.NamedBlobImage(zptlogo, filename=u"zpt.gif") >>> container.blobimage.data == zptlogo True >>> container.blobimage.contentType 'image/gif' >>> print(container.blobimage.filename) zpt.gif
注意,可以强制设置MIME类型
>>> container.image = namedfile.NamedImage(zptlogo, contentType='image/foo', filename=u"zpt.gif") >>> container.image.data == zptlogo True >>> container.image.contentType 'image/foo' >>> print(container.image.filename) zpt.gif >>> container.blobimage = namedfile.NamedBlobImage(zptlogo, contentType='image/foo', filename=u"zpt.gif") >>> container.blobimage.data == zptlogo True >>> container.blobimage.contentType 'image/foo' >>> print(container.blobimage.filename) zpt.gif
文件名必须设置为Unicode字符串,而不是字节字符串
>>> container.image.filename = b'foo' Traceback (most recent call last): ... zope.schema._bootstrapinterfaces.WrongType: ...
限制媒体类型
可以定义接受的媒体类型,就像HTML文件输入的“accept”属性一样。您可以传递文件扩展名或媒体类型值的元组
>>> class IFileContainerConstrained(Interface): ... file = field.NamedFile(title=u"File", accept=("text/plain", ".pdf")) >>> @implementer(IFileContainerConstrained) ... class FileContainerConstrained: ... __allow_access_to_unprotected_subobjects__ = 1 ... def __init__(self): ... self.file = namedfile.NamedFile() >>> container_constrained = FileContainerConstrained()
添加有效的文件类型并检查通过。注意,验证逻辑是由框架调用的,不需要像在这个测试中那样手动调用。
>>> container_constrained.file = namedfile.NamedFile( ... 'dummy test data', ... filename=u"test.txt" ... ) >>> IFileContainerConstrained["file"].validate(container_constrained.file) >>> container_constrained.file = namedfile.NamedFile( ... 'dummy test data', ... filename=u"test.pdf" ... ) >>> IFileContainerConstrained["file"].validate(container_constrained.file)
添加无效的文件类型并检查失败,返回ValidationError
>>> container_constrained.file = namedfile.NamedFile( ... 'dummy test data', ... filename=u"test.wav" ... ) >>> IFileContainerConstrained["file"].validate(container_constrained.file) Traceback (most recent call last): ... plone.namedfile.field.InvalidFile: ('audio/x-wav', 'file')
下载视图
此软件包还包括一个视图,可用于下载文件。这将设置Content-Disposition,以确保浏览器下载文件而不是显示它。要使用它,链接到../context-object/@@download/fieldname,其中fieldname是在上下文对象中存储命名文件的属性名称。
我们将使用模拟请求进行测试,模拟遍历
>>> from plone.namedfile.browser import Download >>> from zope.publisher.browser import TestRequest >>> request = TestRequest() >>> download = Download(container, request).publishTraverse(request, 'simple') >>> bytearray(download()) bytearray(b'dummy test data') >>> request.response.getHeader('Content-Length') '15' >>> request.response.getHeader('Content-Type') 'text/plain' >>> request.response.getHeader('Content-Disposition') "attachment; filename*=UTF-8''test.txt" >>> request = TestRequest() >>> download = Download(container, request).publishTraverse(request, 'blob') >>> data = download() >>> bytearray(hasattr(data, 'read') and data.read() or data) bytearray(b'dummy test data') >>> request.response.getHeader('Content-Length') '15' >>> request.response.getHeader('Content-Type') 'text/plain' >>> request.response.getHeader('Content-Disposition') "attachment; filename*=UTF-8''test.txt" >>> request = TestRequest() >>> download = Download(container, request).publishTraverse(request, 'image') >>> download() == zptlogo True >>> request.response.getHeader('Content-Length') '341' >>> request.response.getHeader('Content-Type') 'image/foo' >>> request.response.getHeader('Content-Disposition') "attachment; filename*=UTF-8''zpt.gif" >>> request = TestRequest() >>> download = Download(container, request).publishTraverse(request, 'blobimage') >>> data = download() >>> (hasattr(data, 'read') and data.read() or data) == zptlogo True >>> request.response.getHeader('Content-Length') '341' >>> request.response.getHeader('Content-Type') 'image/foo' >>> request.response.getHeader('Content-Disposition') "attachment; filename*=UTF-8''zpt.gif"
范围支持
检查部分请求支持
>>> request = TestRequest() >>> download = Download(container, request).publishTraverse(request, 'blobimage') >>> data = download() >>> request.response.getHeader('Content-Length') '341' >>> request.response.getHeader('Accept-Ranges') 'bytes'
请求特定范围
>>> request = TestRequest(environ={'HTTP_RANGE': 'bytes=0-99'}) >>> download = Download(container, request).publishTraverse(request, 'blobimage') >>> data = download() >>> request.response.getStatus() 206 >>> len(hasattr(data, 'read') and data.read() or data) 100
Content-Length标头现在指示请求范围的大小(而不是整个图像的大小)。Content-Range响应标头指示该部分消息在完整资源中的位置。
>>> request.response.getHeader('Content-Length') '100' >>> request.response.getHeader('Content-Range') 'bytes 0-99/341'
显示文件视图
此软件包还包括一个视图,可用于在浏览器中显示文件。要使用它,链接到../context-object/@@display-file/fieldname,其中fieldname是在上下文对象中存储命名文件的属性名称。
我们将使用模拟请求进行测试,模拟遍历
>>> from plone.namedfile.browser import DisplayFile >>> from zope.publisher.browser import TestRequest >>> request = TestRequest() >>> display_file = DisplayFile(container, request).publishTraverse(request, 'simple') >>> bytearray(display_file()) bytearray(b'dummy test data') >>> request.response.getHeader('Content-Length') '15' >>> request.response.getHeader('Content-Type') 'text/plain' >>> request.response.getHeader('Content-Disposition') >>> request = TestRequest() >>> display_file = DisplayFile(container, request).publishTraverse(request, 'blob') >>> data = display_file() >>> bytearray(hasattr(data, 'read') and data.read() or data) bytearray(b'dummy test data') >>> request.response.getHeader('Content-Length') '15' >>> request.response.getHeader('Content-Type') 'text/plain' >>> request.response.getHeader('Content-Disposition') >>> request = TestRequest() >>> display_file = DisplayFile(container, request).publishTraverse(request, 'image') >>> display_file() == zptlogo True >>> request.response.getHeader('Content-Length') '341' >>> request.response.getHeader('Content-Type') 'image/foo'
由于Content-Type未知,我们不相信它,并拒绝内联显示。我们选择下载。
>>> request.response.getHeader('Content-Disposition') "attachment; filename*=UTF-8''zpt.gif">>> request = TestRequest() >>> display_file = DisplayFile(container, request).publishTraverse(request, 'blobimage') >>> data = display_file() >>> (hasattr(data, 'read') and data.read() or data) == zptlogo True >>> request.response.getHeader('Content-Length') '341' >>> request.response.getHeader('Content-Type') 'image/foo' >>> request.response.getHeader('Content-Disposition') "attachment; filename*=UTF-8''zpt.gif"
指定主字段
要在URL中不指定字段的情况下使用@@download视图,必须使用适配器注册主字段信息。(例如,plone.dexterity框架可能已经为您完成了这项工作。)
>>> from plone.rfc822.interfaces import IPrimaryFieldInfo >>> from zope.component import adapter >>> @implementer(IPrimaryFieldInfo) ... @adapter(IFileContainer) ... class FieldContainerPrimaryFieldInfo(object): ... fieldname = 'simple' ... field = IFileContainer['simple'] ... def __init__(self, context): ... self.value = context.simple >>> from zope.component import getSiteManager >>> components = getSiteManager() >>> components.registerAdapter(FieldContainerPrimaryFieldInfo)
我们将使用模拟请求进行测试,模拟遍历
>>> request = TestRequest() >>> download = Download(container, request) >>> bytearray(download()) bytearray(b'dummy test data') >>> request.response.getHeader('Content-Length') '15' >>> request.response.getHeader('Content-Type') 'text/plain' >>> request.response.getHeader('Content-Disposition') "attachment; filename*=UTF-8''test.txt"
图像缩放
此软件包可以处理在NamedImage或NamedBlobImage字段中存储的任意尺寸图像缩放版本的创作、存储和检索。
图像缩放通过提供plone.namedfile.interfaces.IImageScaleTraversable的任何项可用的@@images视图进行访问。您可以通过几种方式从页面模板中引用缩放。
为了完全控制,您可以显式生成标签
<img tal:define="images context/@@images; thumbnail python: images.scale('image', width=64, height=64);" tal:condition="thumbnail" tal:attributes="src thumbnail/url; width thumbnail/width; height thumbnail/height" />
这将创建一个最多64 x 64像素的图像缩小版本,存储在“图像”字段中。它还允许传递plone.scale中支持的scaleImage函数的额外参数,例如mode或quality。
为了使用额外参数自动生成标签,您将使用
<img tal:define="images context/@@images" tal:replace="structure python: images.tag('image', width=1200, height=800, mode='contain')" />
您可以通过调用提供plone.namedfile.interfaces.IAvailableSizes的实用程序来访问预定义的命名缩放大小,而不是每次访问缩放时都硬编码维度。缩放大小可以通过调用返回缩放名称 => (宽度,高度)字典的实用程序找到。然后可以通过以下方式访问名为“mini”的缩放
<img tal:define="images context/@@images" tal:replace="structure python: images.tag('image', scale='mini')" />
这将使用预定义的缩放大小“mini”来确定所需的图像尺寸,但仍允许传递额外参数。
可以使用方便的快捷方式来实现选项3
<img tal:replace="structure context/@@images/image/mini" />
最后,此快捷方式也可以用于渲染未缩放的图像
<img tal:replace="structure context/@@images/image" />
项目详情
下载文件
下载适合您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。