Commits

Christopher Grebs  committed 1f4bb23

Implemted saving to stream objects.

This is required if one tries to implement chunked uploading and needs
to pass a file object to append to.

  • Participants
  • Parent commits 03d743d
  • Branches save-stream

Comments (0)

Files changed (2)

File flaskext/uploads.py

         return ((ext in self.config.allow) or
                 (ext in self.extensions and ext not in self.config.deny))
     
-    def save(self, storage, folder=None, name=None):
+    def save(self, storage, folder=None, destination=None):
         """
         This saves a `werkzeug.FileStorage` into this upload set. If the
         upload is not allowed, an `UploadNotAllowed` error will be raised.
         
         :param storage: The uploaded file to save.
         :param folder: The subfolder within the upload set to save to.
-        :param name: The name to save the file as. If it ends with a dot, the
-                     file's extension will be appended to the end. (If you
-                     are using `name`, you can include the folder in the
-                     `name` instead of explicitly using `folder`, i.e.
-                     ``uset.save(file, name="someguy/photo_123.")``
+        :param destination: The name to save the file as or a file object.
+                            If the name ends with a a dot, the
+                            file's extension will be appended to the end. (If you
+                            are using `name`, you can include the folder in the
+                            `name` instead of explicitly using `folder`, i.e.
+                            ``uset.save(file, name="someguy/photo_123.")``
         """
         if not isinstance(storage, FileStorage):
             raise TypeError("storage must be a werkzeug.FileStorage")
         
-        if folder is None and name is not None and "/" in name:
-            folder, name = name.rsplit("/", 1)
-        
         basename = lowercase_ext(secure_filename(storage.filename))
-        if name:
+        dst = None
+        if destination:
+            if isinstance(destination, basestring):
+                name = destination
+            else:
+                name = FileStorage(destination).filename
+                dst = destination
+     
+            if folder is None and name is not None and "/" in name:
+                folder, name = name.rsplit("/", 1)
+
             if name.endswith('.'):
                 basename = name + extension(basename)
             else:
                 basename = name
-        
+        else:
+            name = destination
+
         if not self.file_allowed(storage, basename):
             raise UploadNotAllowed()
         
             target_folder = self.config.destination
         if not os.path.exists(target_folder):
             os.makedirs(target_folder)
-        if os.path.exists(os.path.join(target_folder, basename)):
+        if os.path.exists(os.path.join(target_folder, basename)) and not dst:
             basename = self.resolve_conflict(target_folder, basename)
         
-        target = os.path.join(target_folder, basename)
+        target = dst or os.path.join(target_folder, basename)
         storage.save(target)
         if folder:
             return posixpath.join(folder, basename)
             content_type=content_type, content_length=content_length,
             headers=None)
         self.saved = None
+        self.saved_stream = False
     
     def save(self, dst, buffer_size=16384):
         """
             self.saved = dst
         else:
             self.saved = dst.name
+            self.saved_stream = True

File tests/test-uploads.py

 :license:   MIT/X11, see LICENSE for details
 """
 from __future__ import with_statement
-import os.path
+import os
+import tempfile
 from flask import Flask, url_for
 from flaskext.uploads import (UploadSet, UploadConfiguration, extension,
     TestingFileStorage, patch_request_class, configure_uploads, addslash,
         uset = UploadSet('files')
         uset._config = Config('/uploads')
         tfs = TestingFileStorage(filename='foo.txt')
-        res = uset.save(tfs, name='file_123.txt')
+        res = uset.save(tfs, destination='file_123.txt')
         assert res == 'file_123.txt'
         assert tfs.saved == '/uploads/file_123.txt'
     
         uset = UploadSet('files')
         uset._config = Config('/uploads')
         tfs = TestingFileStorage(filename='boat.jpg')
-        res = uset.save(tfs, name='photo_123.')
+        res = uset.save(tfs, destination='photo_123.')
         assert res == 'photo_123.jpg'
         assert tfs.saved == '/uploads/photo_123.jpg'
     
         uset = UploadSet('files')
         uset._config = Config('/uploads')
         tfs = TestingFileStorage(filename='boat.jpg')
-        res = uset.save(tfs, folder='someguy', name='photo_123.')
+        res = uset.save(tfs, folder='someguy', destination='photo_123.')
         assert res == 'someguy/photo_123.jpg'
         assert tfs.saved == '/uploads/someguy/photo_123.jpg'
     
         uset = UploadSet('files')
         uset._config = Config('/uploads')
         tfs = TestingFileStorage(filename='boat.jpg')
-        res = uset.save(tfs, name='someguy/photo_123.')
+        res = uset.save(tfs, destination='someguy/photo_123.')
         assert res == 'someguy/photo_123.jpg'
         assert tfs.saved == '/uploads/someguy/photo_123.jpg'
     
         assert res2 == 'myapp.wsgi'
         assert tfs2.saved == '/uploads/myapp.wsgi'
 
+    def test_save_stream(self):
+        uset = UploadSet('files', ALL)
+        uset._config = Config('/uploads')
+        fobj = open(tempfile.mkstemp()[1], 'w')
+        tfs = TestingFileStorage(filename=fobj.name)
+        res = uset.save(tfs, destination=fobj)
+        fobj.close()
+        assert res == fobj.name
+        assert tfs.saved == fobj.name
+        assert tfs.saved_stream is True
+        os.remove(fobj.name)
+
 
 class TestConflictResolution(object):
     def setup(self):