[Zope-Checkins] SVN: Zope/trunk/ Launchpad #143902: Fixed App.ImageFile to use a stream iterator to output the file. Avoid loading the file content when guessing the mimetype and only load the first 1024 bytes of the file when it cannot be guessed from the filename.

Hanno Schlichting plone at hannosch.info
Sat Oct 20 06:31:28 EDT 2007


Log message for revision 80941:
  Launchpad #143902: Fixed App.ImageFile to use a stream iterator to output the file. Avoid loading the file content when guessing the mimetype and only load the first 1024 bytes of the file when it cannot be guessed from the filename.
  

Changed:
  U   Zope/trunk/doc/CHANGES.txt
  U   Zope/trunk/lib/python/App/ImageFile.py

-=-
Modified: Zope/trunk/doc/CHANGES.txt
===================================================================
--- Zope/trunk/doc/CHANGES.txt	2007-10-20 09:57:58 UTC (rev 80940)
+++ Zope/trunk/doc/CHANGES.txt	2007-10-20 10:31:27 UTC (rev 80941)
@@ -175,6 +175,11 @@
 
     Bugs Fixed
 
+      - Launchpad #143902: Fixed App.ImageFile to use a stream iterator to
+        output the file. Avoid loading the file content when guessing the
+        mimetype and only load the first 1024 bytes of the file when it cannot
+        be guessed from the filename.
+
       - Changed PageTemplateFile not to load the file contents on Zope startup
         anymore but on first access instead. This brings them inline with the
         zope.pagetemplate version and speeds up Zope startup.

Modified: Zope/trunk/lib/python/App/ImageFile.py
===================================================================
--- Zope/trunk/lib/python/App/ImageFile.py	2007-10-20 09:57:58 UTC (rev 80940)
+++ Zope/trunk/lib/python/App/ImageFile.py	2007-10-20 10:31:27 UTC (rev 80941)
@@ -15,6 +15,7 @@
 __version__='$Revision: 1.20 $'[11:-2]
 
 import os
+import stat
 import time
 
 import Acquisition
@@ -28,6 +29,8 @@
 
 from zope.contenttype import guess_content_type
 
+from ZPublisher.Iterators import filestream_iterator
+
 class ImageFile(Acquisition.Explicit):
     """Image objects stored in external files."""
 
@@ -48,16 +51,28 @@
             max_age = 3600 # One hour
         self.cch = 'public,max-age=%d' % max_age
 
-        data = open(path, 'rb').read()
-        content_type, enc=guess_content_type(path, data)
+        # First try to get the content_type by name
+        content_type, enc=guess_content_type(path, default='failed')
+
+        if content_type == 'failed':
+            # This failed, lets look into the file content
+            img = open(path, 'rb')
+            data = img.read(1024) # 1k should be enough
+            img.close()
+
+            content_type, enc=guess_content_type(path, data)
+
         if content_type:
             self.content_type=content_type
         else:
-            self.content_type='image/%s' % path[path.rfind('.')+1:]
-        self.__name__=path[path.rfind('/')+1:]
-        self.lmt=float(os.stat(path)[8]) or time.time()
-        self.lmh=rfc1123_date(self.lmt)
+            ext = os.path.splitext(path)[-1].replace('.', '')
+            self.content_type='image/%s' %  ext
 
+        self.__name__ = os.path.split(path)[-1]
+        stat_info = os.stat(path)
+        self.size = stat_info[stat.ST_SIZE]
+        self.lmt = float(stat_info[stat.ST_MTIME]) or time.time()
+        self.lmh = rfc1123_date(self.lmt)
 
     def index_html(self, REQUEST, RESPONSE):
         """Default document"""
@@ -67,7 +82,8 @@
         RESPONSE.setHeader('Content-Type', self.content_type)
         RESPONSE.setHeader('Last-Modified', self.lmh)
         RESPONSE.setHeader('Cache-Control', self.cch)
-        header=REQUEST.get_header('If-Modified-Since', None)
+        RESPONSE.setHeader('Content-Length', str(self.size).replace('L', ''))
+        header = REQUEST.get_header('If-Modified-Since', None)
         if header is not None:
             header=header.split(';')[0]
             # Some proxies seem to send invalid date strings for this
@@ -87,7 +103,7 @@
                     RESPONSE.setStatus(304)
                     return ''
 
-        return open(self.path,'rb').read()
+        return filestream_iterator(self.path, mode='rb')
 
     security.declarePublic('HEAD')
     def HEAD(self, REQUEST, RESPONSE):



More information about the Zope-Checkins mailing list