diff --git a/CHANGES.rst b/CHANGES.rst index 016fdcfc..4ce16473 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -4,7 +4,14 @@ Changes 4.3.1 (unreleased) ------------------ -- TBD +- Fix file uploads on python 3.4 and up. cgi.FieldStorage explicitly + closes files when it is garbage collected. For details, see: + + * http://bugs.python.org/issue18394 + * https://hg.python.org/cpython/rev/c0e9ba7b26d5 + + We now keep a reference to the FieldStorage till we are finished + processing the request. 4.3.0 (2016-07-04) diff --git a/src/zope/publisher/browser.py b/src/zope/publisher/browser.py index 8395a2e8..710793cb 100644 --- a/src/zope/publisher/browser.py +++ b/src/zope/publisher/browser.py @@ -302,6 +302,14 @@ def processInputs(self): args = {'encoding': 'utf-8'} if not PYTHON2 else {} fs = ZopeFieldStorage(fp=fp, environ=env, keep_blank_values=1, **args) + # On python 3.4 and up, FieldStorage explictly closes files + # when it is garbage collected + # see: + # http://bugs.python.org/issue18394 + # https://hg.python.org/cpython/rev/c0e9ba7b26d5 + # so we keep a reference to the FieldStorage till we are + # finished processing the request. + self.hold(fs) fslist = getattr(fs, 'list', None) if fslist is not None: diff --git a/src/zope/publisher/tests/test_browserrequest.py b/src/zope/publisher/tests/test_browserrequest.py index 250f93ce..767bebb7 100644 --- a/src/zope/publisher/tests/test_browserrequest.py +++ b/src/zope/publisher/tests/test_browserrequest.py @@ -217,6 +217,8 @@ def testFileUploadPost(self): request.processInputs() self.assertEqual(request.form['upload'].filename, 'notepad.exe') + # Test that we can actually read the file data + self.assertEqual(request.form['upload'].read(), b'Some data') def testDefault2(self): extra = {'PATH_INFO': '/folder/item2/view'}