134 lines
4.2 KiB
JavaScript
134 lines
4.2 KiB
JavaScript
|
|
const getChunks = (file, chunkSize) => {
|
|
const chunks = [];
|
|
let start = 0;
|
|
let end = Math.min(chunkSize, file.size);
|
|
|
|
while (start < end)
|
|
{
|
|
chunks.push(file.slice(start, end));
|
|
start = end;
|
|
end = Math.min(start + chunkSize, file.size);
|
|
}
|
|
|
|
return chunks;
|
|
};
|
|
|
|
const uploadChunk = (url, chunk, headers) => {
|
|
return fetch(url, {
|
|
method: 'POST',
|
|
body: chunk,
|
|
headers,
|
|
}).then(response => response.json()).then(json => {if(json.result == 'fail') return Promise.reject(json);})
|
|
}
|
|
|
|
function uploadFileByChunk(url, file, chunkSize = 1024 * 1024, onProgress = null)
|
|
{
|
|
const chunks = getChunks(file, chunkSize);
|
|
let i = 0;
|
|
|
|
return new Promise((resolve, reject) => {
|
|
const uploadNextChunk = () => {
|
|
if(i >= chunks.length)
|
|
{
|
|
if(typeof onProgress === 'function') onProgress(1);
|
|
resolve();
|
|
return;
|
|
}
|
|
|
|
const headers = {
|
|
'X-CHUNK-INDEX': i,
|
|
'X-TOTAL-CHUNKS': chunks.length,
|
|
'X-FILENAME': encodeURIComponent(file.name),
|
|
'X-FILESIZE': file.size,
|
|
};
|
|
uploadChunk(url, chunks[i], headers)
|
|
.then(() => {
|
|
i++;
|
|
if(typeof onProgress === 'function') onProgress(i / chunks.length);
|
|
uploadNextChunk();
|
|
})
|
|
.catch(reject);
|
|
};
|
|
|
|
uploadNextChunk();
|
|
});
|
|
};
|
|
|
|
window.uploadImages = function(selector, options, $uploadBtn)
|
|
{
|
|
const $fileBox = $(selector);
|
|
const fileBox = $fileBox.zui();
|
|
const files = fileBox.$.files;
|
|
|
|
if(!files.length)
|
|
{
|
|
if(!$uploadBtn.hasClass('disabled')) zui.Modal.alert(options.errorUploadEmpty);
|
|
return;
|
|
}
|
|
|
|
const progressMap = new Map();
|
|
let uploadedCount = 0;
|
|
$uploadBtn.attr('disabled', 'disabled');
|
|
$uploadBtn.find('.as-progress').text(' 0%');
|
|
const render = () =>
|
|
{
|
|
fileBox.render({disabled: true, itemProps: (file) =>
|
|
{
|
|
const progress = progressMap.get(file.file);
|
|
if(progress === undefined) return {};
|
|
if(progress === 1) return {icon: 'check text-success absolute right-0 bottom-2'};
|
|
|
|
return {title: Math.round(progress * 100) + '% | ' + file.name};
|
|
}});
|
|
};
|
|
|
|
render();
|
|
for(const file of files)
|
|
{
|
|
uploadFileByChunk(options.uploadUrl, file, options.chunkSize, function(progress)
|
|
{
|
|
progressMap.set(file, progress);
|
|
render();
|
|
$uploadBtn.find('.as-progress').text(' ' + Math.round((uploadedCount + progress) / files.length * 100) + '%' );
|
|
}).then(() =>
|
|
{
|
|
uploadedCount++;
|
|
if(uploadedCount === files.length)
|
|
{
|
|
const modalID = $uploadBtn.closest('.modal').attr('id');
|
|
zui.Modal.hide('#' + modalID);
|
|
|
|
const $form = $('body').find('form.form-batch[data-zui-batchform]');
|
|
const $modal = $form.closest('.modal')
|
|
if($modal.length > 0)
|
|
{
|
|
$.ajax(
|
|
{
|
|
url: options.locateUrl,
|
|
headers:{'X-Zui-Modal': true},
|
|
dataType: 'json',
|
|
success: function(data)
|
|
{
|
|
$modal.find('[data-zui-ajaxform]').zui('ajaxform').destroy();
|
|
$modal.find('[data-zui-batchform]').zui('batchForm').destroy();
|
|
setTimeout(function()
|
|
{
|
|
loadModal(data.load, $modal.attr('id'));
|
|
}, 500);
|
|
}
|
|
});
|
|
return;
|
|
}
|
|
loadPage(options.locateUrl);
|
|
}
|
|
}).catch(error =>
|
|
{
|
|
$uploadBtn.removeAttr('disabled');
|
|
$uploadBtn.find('.as-progress').text('');
|
|
fileBox.render({disabled: false});
|
|
if(typeof(error.message) != 'undefined') zui.Modal.alert(error.message);
|
|
});
|
|
}
|
|
};
|