Index: django/contrib/uploadprogress/__init__.py
===================================================================
Index: django/contrib/uploadprogress/models.py
===================================================================
--- django/contrib/uploadprogress/models.py	(revision 0)
+++ django/contrib/uploadprogress/models.py	(revision 0)
@@ -0,0 +1,73 @@
+"""
+Models file for a simple file upload progress application.
+This cause the file progress to be stored in the database.
+To activate:
+1) Add 'django.contrib.uploadprogress.middleware.FileProgressDB'
+   to your MIDDLEWARE_CLASSES setting.
+2) Add 'django.contrib.uploadprogress' to your INSTALLED_APPS.
+
+"""
+
+from django.db import models
+import pickle
+import datetime
+
+class FileProgress(models.Model):
+
+    remote_addr = models.CharField(maxlength=64)
+    progress_id = models.CharField(maxlength=32)
+    progress_text = models.TextField(editable = False)
+    last_ts     = models.DateTimeField()
+
+    class Meta:
+        verbose_name_plural = 'File Progresses'
+        unique_together = (('remote_addr',
+                           'progress_id',
+                           ),
+                           )
+
+    class Admin:
+        pass
+
+    def __str__(self):
+        return 'File Progress for "%s" and IP "%s".' % (self.progress_id, self.remote_addr)
+
+    def _get_dict(self):
+        """
+        Returns a dictionary object.
+        """
+        if hasattr(self, '_progress_dict'):
+            return self._progress_dict
+        
+        if not self.progress_text:
+            self._progress_dict = {}
+            return {}
+
+        try:
+            self._progress_dict = pickle.loads(self.progress_text)
+        except:
+            self._progress_dict = {}
+
+        return self._progress_dict
+
+    def _set_dict(self, dict):
+        """
+        Sets a dictionary object.
+        """
+        self._progress_dict = dict
+
+    progress = property(_get_dict, _set_dict)
+
+    def save(self, *args, **kwargs):
+        """
+        Pickles the dictionary representation
+        of the progress.
+        """
+        try:
+            self.progress_text = pickle.dumps(self.progress)
+        except:
+            pass
+
+        self.last_ts = datetime.datetime.now()
+
+        return super(FileProgress, self).save(*args, **kwargs)
Index: django/contrib/uploadprogress/middleware/uploadcache.py
===================================================================
--- django/contrib/uploadprogress/middleware/uploadcache.py	(revision 0)
+++ django/contrib/uploadprogress/middleware/uploadcache.py	(revision 0)
@@ -0,0 +1,53 @@
+"""
+Example middleware to process uploads using the cache framework.
+"""
+from django.core.cache import cache
+from django.conf import settings
+
+UPLOAD_CACHE_PREFIX = getattr(settings, 'UPLOAD_CACHE_PREFIX', 'UPLOAD_PROGRESS_')
+
+class FileProgressStore(object):
+
+    def _get_key(self, request):
+        """
+        Returns the cache prefix for any cache key.
+        Uses the IP Address as well as the randomly generated uuid.
+        """
+        
+        if hasattr(self, '_cache_key'):
+            return self._cache_key
+        
+        self._cache_key = '%s__%s__%s' % \
+                           (UPLOAD_CACHE_PREFIX,
+                            request.META['REMOTE_ADDR'],
+                            request.META['UPLOAD_PROGRESS_ID'],)
+
+        return self._cache_key
+
+    def __init__(self, UploadException):
+        self.uploadException = UploadException
+
+    def __get__(self, request, HttpRequest):
+        return cache.get(self._get_key(request), {})
+
+    def __set__(self, request, new_val):
+        received_size = total_size = -1
+        try:
+            total_size = int(new_val['size'])
+        except:
+            pass
+
+        try:
+            received_size = int(new_val['received'])
+        except:
+            pass
+        
+        cache.set(self._get_key(request), new_val)
+
+    def __delete__(self, request):
+        cache.delete(self._get_key(request))
+
+class FileProgressCached(object):
+
+    def process_upload(self, UploadException):
+        return FileProgressStore(UploadException)
Index: django/contrib/uploadprogress/middleware/uploaddb.py
===================================================================
--- django/contrib/uploadprogress/middleware/uploaddb.py	(revision 0)
+++ django/contrib/uploadprogress/middleware/uploaddb.py	(revision 0)
@@ -0,0 +1,37 @@
+"""
+Example middleware to process uploads using a database model.
+"""
+from django.contrib.uploadprogress.models import FileProgress
+from django.conf import settings
+import pickle
+
+UPLOAD_CACHE_PREFIX = getattr(settings, 'UPLOAD_CACHE_PREFIX', 'UPLOAD_PROGRESS')
+
+class FileProgressDBStore(object):
+
+    def _get_db_row(self, request):
+        if not hasattr(self, '_db_row'):
+            self._db_row, created = FileProgress.objects.get_or_create(
+                                                 remote_addr = request.META['REMOTE_ADDR'],
+                                                 progress_id = request.META['UPLOAD_PROGRESS_ID'])
+
+        return self._db_row
+
+    def __init__(self, UploadException):
+        self.uploadException = UploadException
+
+    def __get__(self, request, HttpRequest):
+        return self._get_db_row(request).progress
+
+    def __set__(self, request, new_val):
+        row = self._get_db_row(request)
+        row.progress = new_val
+        row.save()
+
+    def __delete__(self, request):
+        self._get_db_row(request).delete()
+
+class FileProgressDB(object):
+
+    def process_upload(self, UploadException):
+        return FileProgressDBStore(UploadException)
Index: django/contrib/uploadprogress/middleware/__init__.py
===================================================================
--- django/contrib/uploadprogress/middleware/__init__.py	(revision 0)
+++ django/contrib/uploadprogress/middleware/__init__.py	(revision 0)
@@ -0,0 +1,3 @@
+from django.contrib.uploadprogress.middleware.uploaddb import FileProgressDB
+from django.contrib.uploadprogress.middleware.uploadcache import FileProgressCached
+
