Works with any backend npm install Zero dependencies

Kitchen Sink (Everything)

Every major feature combined in one demo: chunked, validated, image-processed, hashed, persistent, with full event logging.

Files0
Speed-
Progress0%
Completed0
(function() {
 var logEl = document.getElementById('log');
 function log(m) { var d = document.createElement('div'); d.className='pkg-log-entry'; d.textContent=new Date().toLocaleTimeString()+' '+m; logEl.appendChild(d); logEl.scrollTop=logEl.scrollHeight; }
 document.getElementById('clear-log').addEventListener('click', function() { logEl.innerHTML=''; });

 var u = new MultipleUpload('#demo', {
 uploadUrl: '/api/upload',
 multiple: true,
 autoUpload: false,
 chunked: true,
 chunkSize: '1MB',
 chunkConcurrency: 2,
 concurrency: 2,
 retries: 2,
 retryBackoff: 'exponential',
 maxFileSize: '50MB',
 allowedExtensions: '.jpg,.jpeg,.png,.gif,.webp,.pdf,.doc,.docx,.xls,.xlsx,.zip,.mp4,.txt',
 preventDuplicates: true,
 showThumbnails: true,
 removable: true,
 confirmRemove: true,
 paste: true,
 fullPageDrop: true,
 autoOrient: true,
 imageResize: { maxWidth: 1920, maxHeight: 1920, quality: 0.9 },
 watermark: { text: 'DEMO', fontSize: 24, position: 'bottom-right', color: 'rgba(0,0,0,0.15)' },
 computeHash: true,
 hashAlgorithm: 'sha256',
 persistState: true,
 persistKey: 'kitchen-sink-demo',
 onFileAdded: function(t) { log('+ ' + t.fileName); document.getElementById('ks-files').textContent = u.tasks.length; },
 onTaskProgress: function(t) {
 document.getElementById('ks-speed').textContent = MultipleUpload.formatSize(t.speed) + '/s';
 document.getElementById('ks-pct').textContent = t.progress + '%';
 },
 onTaskComplete: function(t) { log('Done: ' + t.fileName); document.getElementById('ks-done').textContent = u.getCompletedFiles().length; },
 onTaskError: function(t,e) { log('ERR: ' + t.fileName + ' ' + e); },
 onChunkComplete: function(f,i,n) { log('Chunk ' + (i+1) + '/' + n + ' ' + f.name); },
 onQueueComplete: function(f) { log('=== ALL DONE: ' + f.length + ' files ==='); },
 onHashComputed: function(t,h) { log('Hash: ' + t.fileName + ' ' + h.slice(0,16) + '...'); },
 onValidationError: function(m,n) { log('INVALID: ' + (n||'') + ' ' + m); }
 });
 document.getElementById('btn-upload').onclick = function() { u.upload(); };
 document.getElementById('btn-pause').onclick = function() { u.pause(); };
 document.getElementById('btn-resume').onclick = function() { u.resume(); };
 document.getElementById('btn-cancel').onclick = function() { u.cancel(); };
 document.getElementById('btn-reset').onclick = function() { u.reset(); };
})();

Event Log

Everything switched on at once

Chunking, concurrency, retries, hashing, image processing, persistence and the full callback surface, all in one configuration. It is a reference for what can be combined, not a recommendation — almost no real application wants all of it.

Start from the plain case

Each feature adds something to the server side or to the time before an upload starts. Turn them on when a specific problem calls for one: chunking when files are large, hashing when you need identity, persistence when sessions are long. A configuration assembled that way is one you can explain.