# 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" /> 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>