Login

Upload, Progressbar with sessions

Author:
revolunet
Posted:
August 22, 2008
Language:
Python
Version:
.96
Score:
1 (after 1 ratings)

This script is an adaptation from http://www.djangosnippets.org/snippets/678/ . Here, it doesnt use the cache middleware but relies on sessions.

The script set a session cookie to identify the upload and track it to make it available for a progress bar like this one : http://www.djangosnippets.org/snippets/679/ . Note the progress bar cannot work with development server as it is single-threaded. Tested with apache/mod_python and mod_wsgi.

any comments appreciated ;)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
# views.py

from django.core.files.uploadhandler import FileUploadHandler,    UploadFileException   

# class who handles the upload
class ProgressUploadHandler(FileUploadHandler):
    """
    Download the file and store progression in the session
    """
    def __init__(self, request=None, outPath="/tmp"):
        super(ProgressUploadHandler, self).__init__(request)
        self.progress_id = None
        self.cache_key = None
        self.request = request
        self.outPath = outPath
        self.destination = None

    def handle_raw_input(self, input_data, META, content_length, boundary, encoding=None):
        self.content_length = content_length
        if 'X-Progress-ID' in self.request.GET :
            self.progress_id = self.request.GET['X-Progress-ID']
        elif 'X-Progress-ID' in self.request.META:
            self.progress_id = self.request.META['X-Progress-ID']
        if self.progress_id:
           self.cache_key = self.progress_id
           self.request.session['upload_progress_%s' % self.cache_key] =  {
                'length': self.content_length,
                'uploaded' : 0
           }

    def new_file(self, field_name, file_name, content_type, content_length, charset=None):
        #if not is_valid_upload(file_name):         # here you can use a function to filter uploaded files.
        #    raise    UploadFileException , "forbidden file type" 
        self.outPath = os.path.join(self.outPath, file_name)
        self.destination = open(self.outPath, 'wb+')
        pass

    def receive_data_chunk(self, raw_data, start):
        data = self.request.session['upload_progress_%s' % self.cache_key]
        data['uploaded'] += self.chunk_size
        self.request.session['upload_progress_%s' % self.cache_key] = data
        self.request.session.save()
        self.destination.write( raw_data)
        # data wont be passed to any other handler
        return None
    
    def file_complete(self, file_size):
        pass

    def upload_complete(self):
       try:
        self.destination.close()
       except:
        pass
       del self.request.session['upload_progress_%s' % self.cache_key]
       
       
# view that display the current upload progress (json)
def upload_progress(request):
    """
    Return JSON object with information about the progress of an upload.
    """
    progress_id = ''
    if 'X-Progress-ID' in request.GET:
        progress_id = request.GET['X-Progress-ID']
    elif 'X-Progress-ID' in request.META:
        progress_id = request.META['X-Progress-ID']
    if progress_id:
        cache_key = "%s" % (progress_id)
        data = request.session.get('upload_progress_%s' % cache_key, None)
        return HttpResponse(simplejson.dumps(data))
    else:
        return HttpResponseServerError('Server Error: You must provide X-Progress-ID header or query param.')

# view thath launch the upload process 
def upload_form(request):
    if request.method == 'POST':
        outPath = os.path.join(settings.UPLOAD_ROOT, str(request.user.id))   # set your upload path here
        if not os.path.exists(outPath):
            os.makedirs(outPath)
        request.upload_handlers.insert(0, ProgressUploadHandler(request, outPath)) # place our custom upload in first position
        upload_file = request.FILES.get('file', None)   # start the upload
        return HttpResponse("uploaded ok")


# the html upload form. i use an iframe as target so the page isnt reloaded.
# the upload_form view is used to receive the file

    <form name="upload_form"  id="upload_form" method="POST" enctype="multipart/form-data"target="VIRTUAL" >
        Fichier:  <input type="file" name="file" id="id_file" size="45" style=";height:25px;" /> 
        <button id="upload_submit" onclick="doupload()"  style="height:25px;padding:1px">
        <img src="/media/etiquettes/commons/accept.gif" border="0" />&nbsp;envoyer</button>
        <div id="progress_container" style="display:none;width:300px;border:1px solid red;text-align:left;height:15px">
           <div id='progress' style='background:#CCFF99;text-align:center;display:none;padding:5px;width:0%;color:black;font-size:10px;font-weight:bold;'>0%</div>
        </div>
        <iframe id="VIRTUAL" name="VIRTUAL" style="display:none" width="1" height="1" src="about:blank"></iframe>
    </form>

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 10 months, 3 weeks ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 11 months ago
  3. Serializer factory with Django Rest Framework by julio 1 year, 5 months ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 1 year, 6 months ago
  5. Help text hyperlinks by sa2812 1 year, 7 months ago

Comments

fire-eater (on October 3, 2008):

Can you post a full snippets with the template???

#

Keebs (on December 15, 2008):

Probably a dumb question but what does the doupload() (when you click the button) call? Cos I can't find that call in the ajax script

#

jefftsai2050 (on February 24, 2012):

In receive_data_chunk, +chunksize is not correct since the last chunk the real data size may be not chunksize, you should use len(raw_data)

#

jefftsai2050 (on February 24, 2012):

In IE 9, I found an issue: the .getJSON request may not be in the same session with the upload file request if you request uploading in the first time. I checked the request.session.session_key, and found they were different. :(.

#

Please login first before commenting.