file upload improvements
This commit is contained in:
@ -308,97 +308,202 @@ Oqtane.Interop = {
|
||||
}
|
||||
return files;
|
||||
},
|
||||
uploadFiles: function (posturl, folder, id, antiforgerytoken, jwt) {
|
||||
uploadFiles: async function (posturl, folder, id, antiforgerytoken, jwt, chunksize) {
|
||||
var success = true;
|
||||
var fileinput = document.getElementById('FileInput_' + id);
|
||||
var progressinfo = document.getElementById('ProgressInfo_' + id);
|
||||
var progressbar = document.getElementById('ProgressBar_' + id);
|
||||
|
||||
var totalSize = 0;
|
||||
for (var i = 0; i < fileinput.files.length; i++) {
|
||||
totalSize += fileinput.files[i].size;
|
||||
}
|
||||
let uploadSize = 0;
|
||||
|
||||
if (!chunksize) {
|
||||
chunksize = 1; // 1 MB default
|
||||
}
|
||||
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
progressinfo.setAttribute('style', 'display: inline;');
|
||||
if (fileinput.files.length > 1) {
|
||||
progressinfo.innerHTML = fileinput.files[0].name + ', ...';
|
||||
}
|
||||
else {
|
||||
progressinfo.innerHTML = fileinput.files[0].name;
|
||||
}
|
||||
progressbar.setAttribute('style', 'width: 100%; display: inline;');
|
||||
progressbar.value = 0;
|
||||
}
|
||||
|
||||
const uploadFiles = Array.from(fileinput.files).map(file => {
|
||||
const uploadFile = () => {
|
||||
const chunkSize = chunksize * (1024 * 1024);
|
||||
const totalParts = Math.ceil(file.size / chunkSize);
|
||||
let partCount = 0;
|
||||
|
||||
const uploadPart = () => {
|
||||
const start = partCount * chunkSize;
|
||||
const end = Math.min(start + chunkSize, file.size);
|
||||
const chunk = file.slice(start, end);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
let formdata = new FormData();
|
||||
formdata.append('__RequestVerificationToken', antiforgerytoken);
|
||||
formdata.append('folder', folder);
|
||||
formdata.append('formfile', chunk, file.name);
|
||||
|
||||
var credentials = 'same-origin';
|
||||
var headers = new Headers();
|
||||
headers.append('PartCount', partCount + 1);
|
||||
headers.append('TotalParts', totalParts);
|
||||
if (jwt !== "") {
|
||||
headers.append('Authorization', 'Bearer ' + jwt);
|
||||
credentials = 'include';
|
||||
}
|
||||
|
||||
return fetch(posturl, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
credentials: credentials,
|
||||
body: formdata
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
if (progressinfo !== null) {
|
||||
progressinfo.innerHTML = 'Error: ' + response.statusText;
|
||||
}
|
||||
throw new Error('Failed');
|
||||
}
|
||||
return;
|
||||
})
|
||||
.then(data => {
|
||||
partCount++;
|
||||
if (progressbar !== null) {
|
||||
uploadSize += chunk.size;
|
||||
var percent = Math.ceil((uploadSize / totalSize) * 100);
|
||||
progressbar.value = (percent / 100);
|
||||
}
|
||||
if (partCount < totalParts) {
|
||||
uploadPart().then(resolve).catch(reject);
|
||||
}
|
||||
else {
|
||||
resolve(data);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return uploadPart();
|
||||
};
|
||||
|
||||
return uploadFile();
|
||||
});
|
||||
|
||||
try {
|
||||
await Promise.all(uploadFiles);
|
||||
} catch (error) {
|
||||
success = false;
|
||||
}
|
||||
|
||||
fileinput.value = '';
|
||||
return success;
|
||||
},
|
||||
uploadFile: function (posturl, folder, id, antiforgerytoken, jwt, chunksize, totalsize, file) {
|
||||
var fileinput = document.getElementById('FileInput_' + id);
|
||||
var progressinfo = document.getElementById('ProgressInfo_' + id);
|
||||
var progressbar = document.getElementById('ProgressBar_' + id);
|
||||
|
||||
if (file === null && fileinput !== null) {
|
||||
file = fileinput.files[0];
|
||||
totalsize = file.size;
|
||||
}
|
||||
|
||||
if (progressinfo !== null && progressbar !== null && fileinput.files.length === 1) {
|
||||
progressinfo.setAttribute("style", "display: inline;");
|
||||
progressinfo.innerHTML = '';
|
||||
progressinfo.innerHTML = file.name;
|
||||
progressbar.setAttribute("style", "width: 100%; display: inline;");
|
||||
progressbar.value = 0;
|
||||
}
|
||||
|
||||
var files = fileinput.files;
|
||||
var totalSize = 0;
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
totalSize = totalSize + files[i].size;
|
||||
if (!chunksize) {
|
||||
chunksize = 1; // 1 MB default
|
||||
}
|
||||
const chunkSize = chunksize * (1024 * 1024);
|
||||
let uploadSize = 0;
|
||||
const totalParts = Math.ceil(file.size / chunkSize);
|
||||
let partCount = 0;
|
||||
const maxThreads = 1;
|
||||
let threadCount = 1;
|
||||
|
||||
var maxChunkSizeMB = 1;
|
||||
var bufferChunkSize = maxChunkSizeMB * (1024 * 1024);
|
||||
var uploadedSize = 0;
|
||||
const uploadPart = () => {
|
||||
const start = partCount * chunkSize;
|
||||
const end = Math.min(start + chunkSize, file.size);
|
||||
const chunk = file.slice(start, end);
|
||||
|
||||
for (var i = 0; i < files.length; i++) {
|
||||
var fileChunk = [];
|
||||
var file = files[i];
|
||||
var fileStreamPos = 0;
|
||||
var endPos = bufferChunkSize;
|
||||
|
||||
while (fileStreamPos < file.size) {
|
||||
fileChunk.push(file.slice(fileStreamPos, endPos));
|
||||
fileStreamPos = endPos;
|
||||
endPos = fileStreamPos + bufferChunkSize;
|
||||
while (threadCount > maxThreads) {
|
||||
// wait for thread to become available
|
||||
}
|
||||
threadCount++;
|
||||
|
||||
var totalParts = fileChunk.length;
|
||||
var partCount = 0;
|
||||
return new Promise((resolve, reject) => {
|
||||
let formdata = new FormData();
|
||||
formdata.append('__RequestVerificationToken', antiforgerytoken);
|
||||
formdata.append('folder', folder);
|
||||
formdata.append('formfile', chunk, file.name);
|
||||
|
||||
while (chunk = fileChunk.shift()) {
|
||||
partCount++;
|
||||
var fileName = file.name + ".part_" + partCount.toString().padStart(3, '0') + "_" + totalParts.toString().padStart(3, '0');
|
||||
|
||||
var data = new FormData();
|
||||
data.append('__RequestVerificationToken', antiforgerytoken);
|
||||
data.append('folder', folder);
|
||||
data.append('formfile', chunk, fileName);
|
||||
var request = new XMLHttpRequest();
|
||||
request.open('POST', posturl, true);
|
||||
var credentials = 'same-origin';
|
||||
var headers = new Headers();
|
||||
headers.append('PartCount', partCount + 1);
|
||||
headers.append('TotalParts', totalParts);
|
||||
if (jwt !== "") {
|
||||
request.setRequestHeader('Authorization', 'Bearer ' + jwt);
|
||||
request.withCredentials = true;
|
||||
headers.append('Authorization', 'Bearer ' + jwt);
|
||||
credentials = 'include';
|
||||
}
|
||||
request.upload.onloadstart = function (e) {
|
||||
if (progressinfo !== null && progressbar !== null && progressinfo.innerHTML === '') {
|
||||
if (files.length === 1) {
|
||||
progressinfo.innerHTML = file.name;
|
||||
}
|
||||
else {
|
||||
progressinfo.innerHTML = file.name + ", ...";
|
||||
}
|
||||
}
|
||||
};
|
||||
request.upload.onprogress = function (e) {
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
var percent = Math.ceil(((uploadedSize + e.loaded) / totalSize) * 100);
|
||||
progressbar.value = (percent / 100);
|
||||
}
|
||||
};
|
||||
request.upload.onloadend = function (e) {
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
uploadedSize = uploadedSize + e.total;
|
||||
var percent = Math.ceil((uploadedSize / totalSize) * 100);
|
||||
progressbar.value = (percent / 100);
|
||||
}
|
||||
};
|
||||
request.upload.onerror = function() {
|
||||
if (progressinfo !== null && progressbar !== null) {
|
||||
if (files.length === 1) {
|
||||
progressinfo.innerHTML = file.name + ' Error: ' + request.statusText;
|
||||
}
|
||||
else {
|
||||
progressinfo.innerHTML = ' Error: ' + request.statusText;
|
||||
}
|
||||
}
|
||||
};
|
||||
request.send(data);
|
||||
}
|
||||
|
||||
if (i === files.length - 1) {
|
||||
fileinput.value = '';
|
||||
}
|
||||
}
|
||||
return fetch(posturl, {
|
||||
method: 'POST',
|
||||
headers: headers,
|
||||
credentials: credentials,
|
||||
body: formdata
|
||||
})
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
if (progressinfo !== null) {
|
||||
progressinfo.innerHTML = ' Error: ' + response.statusText;
|
||||
}
|
||||
throw new Error('Failed');
|
||||
}
|
||||
if (progressbar !== null) {
|
||||
progressbar.value = 1;
|
||||
}
|
||||
return;
|
||||
})
|
||||
.then(data => {
|
||||
partCount++;
|
||||
if (progressbar !== null) {
|
||||
uploadSize += chunk.size;
|
||||
var percent = Math.ceil((uploadSize / totalsize) * 100);
|
||||
progressbar.value = (percent / 100);
|
||||
}
|
||||
threadCount--;
|
||||
if (partCount < totalParts) {
|
||||
uploadPart().then(resolve).catch(reject);
|
||||
}
|
||||
else {
|
||||
resolve(data);
|
||||
}
|
||||
})
|
||||
.catch(error => {
|
||||
reject(error);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
return uploadPart();
|
||||
},
|
||||
refreshBrowser: function (verify, wait) {
|
||||
async function attemptReload (verify) {
|
||||
|
Reference in New Issue
Block a user