1
0
Fork 0
mirror of https://github.com/Ylianst/MeshCentral.git synced 2025-03-09 15:40:18 +00:00

Fixed large file upload to device on mobile site.

This commit is contained in:
Ylian Saint-Hilaire 2021-12-16 16:28:59 -08:00
parent 84a1753ae8
commit 7333c00650

View file

@ -5418,6 +5418,19 @@
p13uploadNextFile(); p13uploadNextFile();
} }
// Perform SHA-384 hashing
const byteToHex = [];
for (var n = 0; n <= 0xff; ++n) { var hexOctet = n.toString(16).padStart(2, '0'); byteToHex.push(hexOctet); }
function arrayBufferToHex(arrayBuffer) { return Array.prototype.map.call(new Uint8Array(arrayBuffer), n => byteToHex[n]).join(''); }
function performHash(data, f) { window.crypto.subtle.digest('SHA-384', data).then(function (v) { f(arrayBufferToHex(v)); }, function () { f(null); }); }
function performHashOnFile(file, f) {
// TODO: At some point, try to make this work for files of unlimited size using a digest stream
var reader = new FileReader();
reader.onerror = function (err) { f(null); }
reader.onload = function () { window.crypto.subtle.digest('SHA-384', reader.result).then(function (v) { f(arrayBufferToHex(v)); }, function () { f(null); }); };
reader.readAsArrayBuffer(file);
}
// Push the next file // Push the next file
function p13uploadNextFile() { function p13uploadNextFile() {
uploadFile.xfilePtr++; uploadFile.xfilePtr++;
@ -5428,13 +5441,15 @@
Q('d2progressBar').max = file.size; Q('d2progressBar').max = file.size;
Q('d2progressBar').value = 0; Q('d2progressBar').value = 0;
if (file.xdata == null) { if (file.xdata == null) {
// Load the data uploadFile.xfile = file;
uploadFile.xreader = new FileReader(); // If the remote file already exists and is smaller then our file, see if we can resume the trasfer
uploadFile.xreader.onload = function () { var f = null;
uploadFile.xdata = uploadFile.xreader.result; for (var i in p13filetree.dir) { if (p13filetree.dir[i].n == file.name) { f = p13filetree.dir[i]; } }
files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength })); if ((f != null) && (f.s <= uploadFile.xfile.size)) {
}; performHashOnFile(uploadFile.xfile, function (hash) { files.sendText(JSON.stringify({ action: 'uploadhash', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, tag: { h: hash.toUpperCase(), s: f.s, skip: f.s == uploadFile.xfile.size } })); });
uploadFile.xreader.readAsArrayBuffer(file); } else {
files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xfile.size }));
}
} else { } else {
// Data already loaded // Data already loaded
uploadFile.xdata = file.xdata; uploadFile.xdata = file.xdata;
@ -5462,24 +5477,44 @@
function p13gotUploadData(cmd) { function p13gotUploadData(cmd) {
if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; } if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
switch (cmd.action) { switch (cmd.action) {
case 'uploadstart': { p13uploadNextPart(false); for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } break; } // Send 8 more blocks of 16k to fill the websocket. case 'uploadstart': { uploadFile.xdataPriming = 8; p13uploadNextPart(false); break; } // Send 8 more blocks of 16k to fill the websocket.
case 'uploadack': { p13uploadNextPart(false); break; } case 'uploadack': { p13uploadNextPart(false); break; }
case 'uploaddone': { if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadNextFile(); } else { p13uploadFileTransferDone(); } break; } case 'uploaddone': { if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadNextFile(); } else { p13uploadFileTransferDone(); } break; }
case 'uploaderror': { p13uploadFileCancel(); break; } case 'uploaderror': { p13uploadFileCancel(); break; }
case 'uploadhash': {
var file = uploadFile.xfiles[uploadFile.xfilePtr];
if (file) {
if (cmd.tag.h === cmd.hash) {
if (cmd.tag.skip) {
p13uploadNextFile();
} else {
uploadFile.xptr = cmd.tag.s;
files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xfile.size, append: true }));
}
} else {
files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xfile.size, append: false }));
}
}
break;
}
} }
} }
// Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file. // Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
function p13uploadNextPart(dataPriming) { function p13uploadNextPart(dataPriming) {
var data = uploadFile.xdata, start = uploadFile.xptr; if (uploadFile.xreader != null) return; // Data reading already in process
if (start >= data.byteLength) { if (uploadFile.xptr >= uploadFile.xfile.size) return;
files.sendText(JSON.stringify({ action: 'uploaddone', reqid: uploadFile.xfilePtr }));
} else {
var end = uploadFile.xptr + 16384; var end = uploadFile.xptr + 16384;
if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; } if (end > uploadFile.xfile.size) { if (dataPriming == true) { return; } end = uploadFile.xfile.size; }
var dataslice = new Uint8Array(data.slice(start, end)) uploadFile.xreader = new FileReader();
uploadFile.xreader.onerror = function (err) { console.log(err); }
uploadFile.xreader.onload = function () {
var data = uploadFile.xreader.result;
delete uploadFile.xreader;
if (data == null) return;
var dataslice = new Uint8Array(data)
if ((dataslice[0] == 123) || (dataslice[0] == 0)) { if ((dataslice[0] == 123) || (dataslice[0] == 0)) {
var datapart = new Uint8Array(end - start + 1); var datapart = new Uint8Array(data.byteLength + 1);
datapart.set(dataslice, 1); // Add a zero char at the start of the send, this will indicate that it's not a JSON command. datapart.set(dataslice, 1); // Add a zero char at the start of the send, this will indicate that it's not a JSON command.
files.send(datapart); files.send(datapart);
} else { } else {
@ -5487,7 +5522,13 @@
} }
uploadFile.xptr = end; uploadFile.xptr = end;
Q('d2progressBar').value = end; Q('d2progressBar').value = end;
if (uploadFile.xptr >= uploadFile.xfile.size) {
files.sendText(JSON.stringify({ action: 'uploaddone', reqid: uploadFile.xfilePtr }));
} else {
if (uploadFile.xdataPriming > 0) { uploadFile.xdataPriming--; p13uploadNextPart(true); }
} }
};
uploadFile.xreader.readAsArrayBuffer(uploadFile.xfile.slice(uploadFile.xptr, end));
} }
// //