跳转到主要内容

文件和图像 -- Zope 3 内容组件

项目描述

此包提供了两个基本的Zope 3内容组件,文件和图像,以及它们符合ZMI规范的浏览器视图。

文件对象

添加文件

您可以从ZMI中的常见任务菜单添加文件对象。

>>> result = http(r"""
... GET /@@contents.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """)
>>> "https://127.0.0.1/@@+/action.html?type_name=zope.app.file.File" in str(result)
True

让我们跟随那个链接。

>>> print(http(r"""
... GET /@@+/action.html?type_name=zope.app.file.File HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """, handle_errors=False))
HTTP/1.1 303 See Other
Content-Length: ...
Location: https://127.0.0.1/+/zope.app.file.File=
<BLANKLINE>

文件添加表单允许您指定内容类型、对象名称,并可选择上传文件的全部内容。

>>> print(http(r"""
... GET /+/zope.app.file.File= HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
    <title>Z3: +</title>
...
...
  <form action="https://127.0.0.1/+/zope.app.file.File%3D"
        method="post" enctype="multipart/form-data">
    <h3>Add a File</h3>
    ...<input class="textType" id="field.contentType"
              name="field.contentType" size="20" type="text" value="" />...
    ...<input class="fileType" id="field.data" name="field.data" size="20"
              type="file" />...
      <div class="controls"><hr />
        <input type="submit" value="Refresh" />
        <input type="submit" value="Add"
               name="UPDATE_SUBMIT" />
        &nbsp;&nbsp;<b>Object Name</b>&nbsp;&nbsp;
        <input type="text" name="add_input_name" value="" />
      </div>
...
  </form>
...

二进制文件

让我们上传一个二进制文件。

>>> print(http(b"""
... POST /+/zope.app.file.File%3D HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------73793505419963331401738523176
...
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="field.contentType"
...
... application/octet-stream
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="field.data"; filename="hello.txt.gz"
... Content-Type: application/x-gzip
...
... \x1f\x8b\x08\x08\xcb\x48\xea\x42\x00\x03\x68\x65\x6c\x6c\x6f\x2e\
... \x74\x78\x74\x00\xcb\x48\xcd\xc9\xc9\xe7\x02\x00\x20\x30\x3a\x36\
... \x06\x00\x00\x00
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="add_input_name"
...
...
... -----------------------------73793505419963331401738523176--
... """))
HTTP/1.1 303 See Other
Content-Length: ...
Content-Type: text/html;charset=utf-8
Location: https://127.0.0.1/@@contents.html
<BLANKLINE>
...

由于我们没有在表单中指定对象名称,Zope 3将使用文件名。

>>> response = http("""
... GET /hello.txt.gz HTTP/1.1
... """)
>>> print(response)
HTTP/1.1 200 OK
Content-Length: 36
Content-Type: application/octet-stream
<BLANKLINE>
...

让我们确保文件的(二进制)内容是正确的

>>> response.getBody() == b'\x1f\x8b\x08\x08\xcbH\xeaB\x00\x03hello.txt\x00\xcbH\xcd\xc9\xc9\xe7\x02\x00 0:6\x06\x00\x00\x00'
True

此外,让我们测试一个(错误)的包含完整路径的文件名,该文件名会生成MS Internet Explorer,Zope应成功处理它并获取实际文件名。让我们用错误的文件名上传相同的文件。

>>> print(http(b"""
... POST /+/zope.app.file.File%3D HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------73793505419963331401738523176
...
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="field.contentType"
...
... application/octet-stream
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="field.data"; filename="c:\\windows\\test.gz"
... Content-Type: application/x-gzip
...
... \x1f\x8b\x08\x08\xcb\x48\xea\x42\x00\x03\x68\x65\x6c\x6c\x6f\x2e\
... \x74\x78\x74\x00\xcb\x48\xcd\xc9\xc9\xe7\x02\x00\x20\x30\x3a\x36\
... \x06\x00\x00\x00
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="add_input_name"
...
...
... -----------------------------73793505419963331401738523176--
... """))
HTTP/1.1 303 See Other
Content-Length: ...
Content-Type: text/html;charset=utf-8
Location: https://127.0.0.1/@@contents.html
<BLANKLINE>
...

文件应保存为“test.gz”,让我们检查其名称和内容。

>>> response = http("""
... GET /test.gz HTTP/1.1
... """)
>>> print(response)
HTTP/1.1 200 OK
Content-Length: 36
Content-Type: application/octet-stream
<BLANKLINE>
...
>>> response.getBody() == b'\x1f\x8b\x08\x08\xcbH\xeaB\x00\x03hello.txt\x00\xcbH\xcd\xc9\xc9\xe7\x02\x00 0:6\x06\x00\x00\x00'
True

文本文件

现在让我们创建一个文本文件。

>>> print(http(r"""
... POST /+/zope.app.file.File%3D HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------167769037320366690221542301033
...
... -----------------------------167769037320366690221542301033
... Content-Disposition: form-data; name="field.contentType"
...
... text/plain
... -----------------------------167769037320366690221542301033
... Content-Disposition: form-data; name="field.data"; filename=""
... Content-Type: application/octet-stream
...
...
... -----------------------------167769037320366690221542301033
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------167769037320366690221542301033
... Content-Disposition: form-data; name="add_input_name"
...
... sample.txt
... -----------------------------167769037320366690221542301033--
... """))
HTTP/1.1 303 See Other
Content-Length: ...
Content-Type: text/html;charset=utf-8
Location: https://127.0.0.1/@@contents.html
<BLANKLINE>
...

由于我们没有上传任何内容,文件最初是空的。

>>> print(http("""
... GET /sample.txt HTTP/1.1
... """))
HTTP/1.1 200 OK
Content-Length: 0
Content-Type: text/plain
Last-Modified: ...
<BLANKLINE>

由于它是一个文本文件,我们可以在网页表单中直接编辑它。

>>> print(http(r"""
... GET /sample.txt/edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """, handle_errors=False))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
    <title>Z3: sample.txt</title>
...
    <form action="https://127.0.0.1/sample.txt/edit.html"
          method="post" enctype="multipart/form-data">
      <div>
        <h3>Change a file</h3>
...<input class="textType" id="field.contentType" name="field.contentType"
          size="20" type="text" value="text/plain"  />...
...<textarea cols="60" id="field.data" name="field.data" rows="15" ></textarea>...
...
        <div class="controls">
          <input type="submit" value="Refresh" />
          <input type="submit" name="UPDATE_SUBMIT"
                 value="Change" />
        </div>
...
    </form>
...

没有字符集信息的text/plain类型的文件可以包含UTF-8文本。因此,您可以使用ASCII文本。

>>> print(http(r"""
... POST /sample.txt/edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------165727764114325486311042046845
...
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.contentType"
...
... text/plain
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.data"
...
... This is a sample text file.
...
... It can contain US-ASCII characters.
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------165727764114325486311042046845--
... """, handle_errors=False))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
    <title>Z3: sample.txt</title>
...
    <form action="https://127.0.0.1/sample.txt/edit.html"
          method="post" enctype="multipart/form-data">
      <div>
        <h3>Change a file</h3>
<BLANKLINE>
        <p>Updated on ...</p>
<BLANKLINE>
      <div class="row">
...<input class="textType" id="field.contentType" name="field.contentType"
          size="20" type="text" value="text/plain"  />...
      <div class="row">
...<textarea cols="60" id="field.data" name="field.data" rows="15"
>This is a sample text file.
<BLANKLINE>
It can contain US-ASCII characters.</textarea></div>
...
        <div class="controls">
          <input type="submit" value="Refresh" />
          <input type="submit" name="UPDATE_SUBMIT"
                 value="Change" />
        </div>
...
    </form>
...

这是文件

>>> print(http(r"""
... GET /sample.txt HTTP/1.1
... """))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/plain
Last-Modified: ...
<BLANKLINE>
This is a sample text file.
<BLANKLINE>
It can contain US-ASCII characters.

非ASCII文本文件

我们还可以在文本文件中使用非ASCII字符。

>>> print(http("""
... POST /sample.txt/edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------165727764114325486311042046845
...
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.contentType"
...
... text/plain
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.data"
...
... This is a sample text file.
...
... It can contain non-ASCII(UTF-8) characters, e.g. \xe2\x98\xbb (U+263B BLACK SMILING FACE).
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------165727764114325486311042046845--
... """))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
    <title>Z3: sample.txt</title>
...
    <form action="https://127.0.0.1/sample.txt/edit.html"
          method="post" enctype="multipart/form-data">
      <div>
        <h3>Change a file</h3>
<BLANKLINE>
        <p>Updated on ...</p>
<BLANKLINE>
      <div class="row">
...<input class="textType" id="field.contentType" name="field.contentType"
          size="20" type="text" value="text/plain"  />...
      <div class="row">
...<textarea cols="60" id="field.data" name="field.data" rows="15"
>This is a sample text file.
<BLANKLINE>
It can contain non-ASCII(UTF-8) characters, e.g. ... (U+263B BLACK SMILING FACE).</textarea></div>
...
        <div class="controls">
          <input type="submit" value="Refresh" />
          <input type="submit" name="UPDATE_SUBMIT"
                 value="Change" />
        </div>
...
    </form>
...

这是文件

>>> response = http(r"""
... GET /sample.txt HTTP/1.1
... """)
>>> print(response)
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/plain
Last-Modified: ...
<BLANKLINE>
This is a sample text file.
<BLANKLINE>
It can contain non-ASCII(UTF-8) characters, e.g. ... (U+263B BLACK SMILING FACE).
>>> u'\u263B' in response.getBody().decode('UTF-8')
True

并且您可以明确指定字符集。请注意,浏览器表单始终是UTF-8。

>>> print(http("""
... POST /sample.txt/edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------165727764114325486311042046845
...
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.contentType"
...
... text/plain; charset=ISO-8859-1
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.data"
...
... This is a sample text file.
...
... It now contains Latin-1 characters, e.g. \xc2\xa7 (U+00A7 SECTION SIGN).
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------165727764114325486311042046845--
... """))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
    <title>Z3: sample.txt</title>
...
    <form action="https://127.0.0.1/sample.txt/edit.html"
          method="post" enctype="multipart/form-data">
      <div>
        <h3>Change a file</h3>
<BLANKLINE>
        <p>Updated on ...</p>
<BLANKLINE>
      <div class="row">
...<input class="textType" id="field.contentType" name="field.contentType"
          size="20" type="text" value="text/plain; charset=ISO-8859-1"  />...
      <div class="row">
...<textarea cols="60" id="field.data" name="field.data" rows="15"
>This is a sample text file.
<BLANKLINE>
It now contains Latin-1 characters, e.g. ... (U+00A7 SECTION SIGN).</textarea></div>
...
        <div class="controls">
          <input type="submit" value="Refresh" />
          <input type="submit" name="UPDATE_SUBMIT"
                 value="Change" />
        </div>
...
    </form>
...

这是文件

>>> response = http(r"""
... GET /sample.txt HTTP/1.1
... """)
>>> print(response)
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/plain; charset=ISO-8859-1
Last-Modified: ...
<BLANKLINE>
This is a sample text file.
<BLANKLINE>
It now contains Latin-1 characters, e.g. ... (U+00A7 SECTION SIGN).

主体实际上编码为ISO-8859-1,而不是UTF-8

>>> response.getBody().splitlines()[-1].decode('latin-1')
'It now contains Latin-1 characters, e.g. \xa7 (U+00A7 SECTION SIGN).'

用户不允许指定无法表示所有字符的字符集。

>>> print(http("""
... POST /sample.txt/edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------165727764114325486311042046845
...
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.contentType"
...
... text/plain; charset=US-ASCII
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.data"
...
... This is a slightly changed sample text file.
...
... It now contains Latin-1 characters, e.g. \xc2\xa7 (U+00A7 SECTION SIGN).
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------165727764114325486311042046845--
... """, handle_errors=False))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
    <title>Z3: sample.txt</title>
...
    <form action="https://127.0.0.1/sample.txt/edit.html"
          method="post" enctype="multipart/form-data">
      <div>
        <h3>Change a file</h3>
<BLANKLINE>
        <p>The character set you specified (US-ASCII) cannot encode all characters in text.</p>
<BLANKLINE>
      <div class="row">
...<input class="textType" id="field.contentType" name="field.contentType" size="20" type="text" value="text/plain; charset=US-ASCII"  />...
      <div class="row">
...<textarea cols="60" id="field.data" name="field.data" rows="15" >This is a slightly changed sample text file.
<BLANKLINE>
It now contains Latin-1 characters, e.g. ... (U+00A7 SECTION SIGN).</textarea></div>
...
        <div class="controls">
          <input type="submit" value="Refresh" />
          <input type="submit" name="UPDATE_SUBMIT"
                 value="Change" />
        </div>
...
    </form>
...

同样,用户不允许指定Python不支持的字符集。

>>> print(http("""
... POST /sample.txt/edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------165727764114325486311042046845
...
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.contentType"
...
... text/plain; charset=I-INVENT-MY-OWN
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="field.data"
...
... This is a slightly changed sample text file.
...
... It now contains just ASCII characters.
... -----------------------------165727764114325486311042046845
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------165727764114325486311042046845--
... """, handle_errors=False))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
    <title>Z3: sample.txt</title>
...
    <form action="https://127.0.0.1/sample.txt/edit.html"
          method="post" enctype="multipart/form-data">
      <div>
        <h3>Change a file</h3>
<BLANKLINE>
        <p>The character set you specified (I-INVENT-MY-OWN) is not supported.</p>
<BLANKLINE>
      <div class="row">
...<input class="textType" id="field.contentType" name="field.contentType" size="20" type="text" value="text/plain; charset=I-INVENT-MY-OWN"  />...
      <div class="row">
...<textarea cols="60" id="field.data" name="field.data" rows="15" >This is a slightly changed sample text file.
<BLANKLINE>
It now contains just ASCII characters.</textarea></div>
...
        <div class="controls">
          <input type="submit" value="Refresh" />
          <input type="submit" name="UPDATE_SUBMIT"
                 value="Change" />
        </div>
...
    </form>
...

如果您欺骗Zope并上传一个与文件内容不匹配的内容类型,您将无法访问编辑视图

>>> print(http(r"""
... GET /hello.txt.gz/@@edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """, handle_errors=True))
HTTP/1.1 200 OK
Content-Length: ...
Content-Type: text/html;charset=utf-8
<BLANKLINE>
...
   <li>The character set specified in the content type (UTF-8) does not match file content.</li>
...

非ASCII文件名

文件名不受ASCII的限制。

>>> print(http(b"""
... POST /+/zope.app.file.File%3D HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Type: multipart/form-data; boundary=---------------------------73793505419963331401738523176
...
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="field.contentType"
...
... application/octet-stream
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="field.data"; filename="bj\xc3\xb6rn.txt.gz"
... Content-Type: application/x-gzip
...
... \x1f\x8b\x08\x08\xcb\x48\xea\x42\x00\x03\x68\x65\x6c\x6c\x6f\x2e\
... \x74\x78\x74\x00\xcb\x48\xcd\xc9\xc9\xe7\x02\x00\x20\x30\x3a\x36\
... \x06\x00\x00\x00
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------73793505419963331401738523176
... Content-Disposition: form-data; name="add_input_name"
...
...
... -----------------------------73793505419963331401738523176--
... """))
HTTP/1.1 303 See Other
Content-Length: ...
Content-Type: text/html;charset=utf-8
Location: https://127.0.0.1/@@contents.html
<BLANKLINE>
...

由于我们没有在表单中指定对象名称,Zope 3将使用文件名。

>>> response = http("""
... GET /bj%C3%B6rn.txt.gz HTTP/1.1
... """)
>>> print(response)
HTTP/1.1 200 OK
Content-Length: 36
Content-Type: application/octet-stream
<BLANKLINE>
...

为DTML页面处理特殊URL

当访问包含head标签的HTML文件页面时,如果没有尾随斜线,则不设置base href。当带有斜线访问时,则是

>>> print(http(r"""
... POST /+/zope.app.file.File%3D HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Length: 610
... Content-Type: multipart/form-data; boundary=---------------------------32826232819858510771857533856
... Referer: https://127.0.0.1:8081/+/zope.app.file.File=
...
... -----------------------------32826232819858510771857533856
... Content-Disposition: form-data; name="field.contentType"
...
... text/html
... -----------------------------32826232819858510771857533856
... Content-Disposition: form-data; name="field.data"; filename=""
... Content-Type: application/octet-stream
...
...
... -----------------------------32826232819858510771857533856
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Add
... -----------------------------32826232819858510771857533856
... Content-Disposition: form-data; name="add_input_name"
...
... file.html
... -----------------------------32826232819858510771857533856--
... """))
HTTP/1.1 303 See Other
...
>>> print(http(r"""
... POST /file.html/edit.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... Content-Length: 507
... Content-Type: multipart/form-data; boundary=---------------------------10196264131256436092131136054
... Referer: https://127.0.0.1:8081/file.html/edit.html
...
... -----------------------------10196264131256436092131136054
... Content-Disposition: form-data; name="field.contentType"
...
... text/html
... -----------------------------10196264131256436092131136054
... Content-Disposition: form-data; name="field.data"
...
... <html>
... <head></head>
... <body>
... <a href="eek.html">Eek</a>
... </body>
... </html>
... -----------------------------10196264131256436092131136054
... Content-Disposition: form-data; name="UPDATE_SUBMIT"
...
... Change
... -----------------------------10196264131256436092131136054--
... """))
HTTP/1.1 200 OK
...
>>> print(http(r"""
... GET /file.html HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """))
HTTP/1.1 200 OK
...
<html>
<head></head>
<body>
<a href="eek.html">Eek</a>
</body>
</html>
>>> print(http(r"""
... GET /file.html/ HTTP/1.1
... Authorization: Basic mgr:mgrpw
... """))
HTTP/1.1 200 OK
...
<html>
<head>
<base href="https://127.0.0.1/file.html" />
</head>
<body>
<a href="eek.html">Eek</a>
</body>
</html>

变更

4.0.0 (2017-05-16)

  • 添加对Python 3.4、3.5、3.6和PyPy的支持。

  • 删除对zope.app.testingzope.app.zcmlfiles等测试依赖项的依赖。

  • 将依赖项从ZODB3更改为persistent,并添加对zope.app.content的缺失依赖。

3.6.1 (2010-09-17)

  • 删除了ZPKG和ZCML的slug。

  • 将一个功能测试从zope.app.http移到这里。

  • 使用Python的doctest而不是已弃用的zope.testing.doctest

3.6.0 (2010-08-19)

  • 更新ftesting.zcml以使用由zope.dublincore 3.7导出的新权限名称。

  • 使用python的doctest而不是已弃用的zope.testing.doctest

3.5.1 (2010-01-08)

  • 由于zope.securitypolicy更新,修复ftesting.zcml。

  • 添加对transaction的缺失依赖。

  • 从zope.contenttype导入内容类型解析器,将zope.publisher减少为测试依赖。

  • 修复使用需要zope.login的新版zope.publisher进行的测试。

3.5.0 (2009-01-31)

  • zope.site替换zope.app.folder的使用。在setup.py中添加缺失的依赖项。

3.4.6 (2009-01-27)

  • 再次删除zope.app.zapi依赖。上一个版本是错误的。我们之前删除了zope.app.zapi的使用,因此我们不再需要它。

3.4.5 (2009-01-27)

  • 添加缺失依赖项:zope.app.zapi

3.4.4 (2008-09-05)

  • 错误:在Internet Explorer中添加文件/图像时,获取实际文件名而不是完整的文件系统路径。

3.4.3 (2008-06-18)

  • 使用IDCTimes接口而不是IZopeDublinCore来确定文件的修改日期。

3.4.2 (2007-11-09)

3.4.1 (2007-10-31)

  • 解决ZopeSecurityPolicy弃用警告。

3.4.0 (2007-10-24)

  • 独立于主要Zope树发布。

下载文件

下载您平台的文件。如果您不确定选择哪个,请了解更多关于安装包的信息。

源分发

zope.app.file-4.0.0.tar.gz (35.3 kB 查看哈希值)

上传于

构建发行版

zope.app.file-4.0.0-py2.py3-none-any.whl (45.6 kB 查看哈希值)

上传于 Python 2 Python 3

由以下支持