Multiple files uploading with Django and valums file-uploader
Step 1: js/html
Upload valums file-uploader:
Include fileuploader.js and fileuploader.css to your page.
Place it there You want to see uploader:
<div id="file-uploader"> <noscript> <p>Please enable JavaScript to use file uploader.</p> <!-- or put a simple form for upload here --> </noscript> </div>
Initialize file-uploader:
var uploader = new qq.FileUploader({ element: document.getElementById('file-uploader'), action: '/server/upload/' });
My configuration for uploader shown on the image:
image_uploader = new qq.FileUploader({ element: lb.find('.js-image-uploader')[0]._, action: '/images/upload/', allowedExtensions: ['jpg', 'jpeg', 'png', 'gif'], sizeLimit: 4194304, template: '<div class="qq-uploader">' + '<div class="qq-upload-drop-area"><span>Drop files here to upload</span></div>' + '<div class="qq-upload-button">Select file</div>' + '<div class="qq-uploads-wrap"><ul class="qq-upload-list"></ul></div>' + '</div>', fileTemplate: '<li>' + '<span class="qq-upload-file"></span>' + '<span class="qq-upload-spinner"></span>' + '<span class="qq-upload-size"></span>' + '<a class="qq-upload-cancel" href="#">Cancel</a>' + '<span class="qq-upload-result"></span>' + '<div class="qq-progress"><span> </span></div>' + '</li>', onComplete: function(id, fileName, responseJson){ var el = lb.image_uploader._getItemByFileId(id); if(responseJson.success){ $(el).find('.qq-upload-result')[0].html('<span style="color: #0a0">Done</span>'); } else { $(el).find('.qq-upload-result')[0].html('<span style="color: #a00">Error</span>'); }; $(el).find('.qq-progress')[0].remove(); }, onProgress: function(id, fileName, loaded, total){ var el = lb.image_uploader._getItemByFileId(id); $(el).find('.qq-progress span')[0].setStyle('width', (loaded/total*300).round() + 'px'); } });
Step 2: Django
import os from django.utils.simplejson import dumps from django.http import HttpResponse, Http404 from django.core.files import locks from django.conf import settings def upload_image(request): if request.method != 'POST' or not request.is_ajax(): raise Http404 caption = request.GET.get('qqfile', '') try: ext = caption.split('.')[-1] caption = caption.split('.')[0] except IndexError: return HttpResponse(dumps({'success': False}), mimetype='application/json') file_name = '%s.%s' % (caption, ext) dir_path = os.path.join(settings.MEDIA_ROOT, 'images') file_path = os.path.join(dir_path, file_name) if os.path.exists(file_path): return HttpResponse(dumps({'success': False}), mimetype='application/json') if not os.path.exists(dir_path) or not os.path.isdir(dir_path): # create a directory, including missing parents, ensuring it has group write permissions old_mask = os.umask(0002) try: os.makedirs(dir_path) finally: os.umask(old_mask) write_mode = ( os.O_WRONLY | os.O_CREAT | os.O_EXCL | getattr(os, 'O_BINARY', 0)) fd = os.open(file_path, write_mode) try: locks.lock(fd, locks.LOCK_EX) while True: buf = request.read(512 * 1024) if buf: os.write(fd, buf) else: break finally: locks.unlock(fd) os.close(fd) return HttpResponse(dumps({'success': True}), mimetype='application/json')
Test:
import os from django.conf import settings from mock import Mock from .views import upload_image def test_upload_image(self): request = Mock() image_file = open( os.path.join(settings.MEDIA_ROOT, 'tests/123.jpg'), 'r') request.raw_post_data = image_file.read() request.method = 'POST' request.is_ajax = lambda : True request.GET = {'qqfile': '123.jpg'} file_path = os.path.join(settings.MEDIA_ROOT, 'images/123.jpg') if os.path.exists(file_path): os.remove(file_path) response = upload_image(request) self.assertTrue(os.path.exists(file_path))
Check out also these:
- https://github.com/GoodCloud/django-ajax-uploader
- http://stackoverflow.com/questions/4750168/fileupload-with-django
Step 3: Use it
File-uploader advantages:
- upload multiple files
- show progress
- cancel uploads
- restrict file extensions and max/min file sizes
- write your own validator
- use your own templates for file-uploader widget
- use your own styles for file-uploader widget
- Drag&Drop feature is enabled by default
Updates
UPD 2013-07-02
New link: http://valums-file-uploader.github.io/file-uploader.
UPD 2013-07-07
Added django code example.
UPD 2015-02-15
Fixed language.
Licensed under CC BY-SA 3.0