Fixed desktop site to allow large uploads to devices.

Ylian Saint-Hilaire committed Dec 16, 2021 at 15:31 UTC 84a1753ae8a2168f01661fb2a192bfc42538a473
1 file changed +38 -29
views/default.handlebars
+38 -29
@@ -10254,6 +10254,13 @@
10254 for (var n = 0; n <= 0xff; ++n) { var hexOctet = n.toString(16).padStart(2, '0'); byteToHex.push(hexOctet); }
10255 function arrayBufferToHex(arrayBuffer) { return Array.prototype.map.call( new Uint8Array(arrayBuffer), n => byteToHex[n] ).join(''); }
10256 function performHash(data, f) { window.crypto.subtle.digest('SHA-384', data).then(function (v) { f(arrayBufferToHex(v)); }, function() { f(null); }); }
10257 + function performHashOnFile(file, f) {
10258 + // TODO: At some point, try to make this work for files of unlimited size using a digest stream
10259 + var reader = new FileReader();
10260 + reader.onerror = function (err) { f(null); }
10261 + reader.onload = function () { window.crypto.subtle.digest('SHA-384', reader.result).then(function (v) { f(arrayBufferToHex(v)); }, function() { f(null); }); };
10262 + reader.readAsArrayBuffer(file);
10263 + }
10264
10265 // Push the next file
10266 function p13uploadNextFile() {
@@ -10265,23 +10272,15 @@
10272 Q('d2progressBar').max = file.size;
10273 Q('d2progressBar').value = 0;
10274 if (file.xdata == null) {
10268 - // Load the data
10269 - uploadFile.xreader = new FileReader();
10270 - uploadFile.xreader.onload = function () {
10271 - uploadFile.xdata = uploadFile.xreader.result;
10272 -
10273 - // If the remote file already exists and is smaller then our file, see if we can resume the trasfer
10274 - var f = null;
10275 - for (var i in p13filetree.dir) { if (p13filetree.dir[i].n == file.name) { f = p13filetree.dir[i]; } }
10276 - if ((f != null) && (f.s <= uploadFile.xreader.result.byteLength)) {
10277 - performHash(uploadFile.xreader.result.slice(0, f.s), function(hash) {
10278 - 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.xreader.result.byteLength } }));
10279 - });
10280 - } else {
10281 - files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
10282 - }
10283 - };
10284 - uploadFile.xreader.readAsArrayBuffer(file);
10275 + uploadFile.xfile = file;
10276 + // If the remote file already exists and is smaller then our file, see if we can resume the trasfer
10277 + var f = null;
10278 + for (var i in p13filetree.dir) { if (p13filetree.dir[i].n == file.name) { f = p13filetree.dir[i]; } }
10279 + if ((f != null) && (f.s <= uploadFile.xfile.size)) {
10280 + 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 } })); });
10281 + } else {
10282 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xfile.size }));
10283 + }
10284 } else {
10285 // Data already loaded
10286 uploadFile.xdata = file.xdata;
@@ -10309,7 +10308,7 @@
10308 function p13gotUploadData(cmd) {
10309 if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
10310 switch (cmd.action) {
10312 - case 'uploadstart': { p13uploadNextPart(false); for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } break; } // Send 8 more blocks of 16k to fill the websocket.
10311 + case 'uploadstart': { uploadFile.xdataPriming = 8; p13uploadNextPart(false); break; } // Send 8 more blocks of 16k to fill the websocket.
10312 case 'uploadack': { p13uploadNextPart(false); break; }
10313 case 'uploaddone': { if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadNextFile(); } else { p13uploadFileTransferDone(); } break; }
10314 case 'uploaderror': { p13uploadFileCancel(); break; }
@@ -10321,10 +10320,10 @@
10320 p13uploadNextFile();
10321 } else {
10322 uploadFile.xptr = cmd.tag.s;
10324 - files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength, append: true }));
10323 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xfile.size, append: true }));
10324 }
10325 } else {
10327 - files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength, append: false }));
10326 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xfile.size, append: false }));
10327 }
10328 }
10329 break;
@@ -10334,15 +10333,19 @@
10333
10334 // 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.
10335 function p13uploadNextPart(dataPriming) {
10337 - var data = uploadFile.xdata, start = uploadFile.xptr;
10338 - if (start >= data.byteLength) {
10339 - files.sendText(JSON.stringify({ action: 'uploaddone', reqid: uploadFile.xfilePtr }));
10340 - } else {
10341 - var end = uploadFile.xptr + 16384;
10342 - if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
10343 - var dataslice = new Uint8Array(data.slice(start, end))
10336 + if (uploadFile.xreader != null) return; // Data reading already in process
10337 + if (uploadFile.xptr >= uploadFile.xfile.size) return;
10338 + var end = uploadFile.xptr + 16384;
10339 + if (end > uploadFile.xfile.size) { if (dataPriming == true) { return; } end = uploadFile.xfile.size; }
10340 + uploadFile.xreader = new FileReader();
10341 + uploadFile.xreader.onerror = function (err) { console.log(err); }
10342 + uploadFile.xreader.onload = function () {
10343 + var data = uploadFile.xreader.result;
10344 + delete uploadFile.xreader;
10345 + if (data == null) return;
10346 + var dataslice = new Uint8Array(data)
10347 if ((dataslice[0] == 123) || (dataslice[0] == 0)) {
10345 - var datapart = new Uint8Array(end - start + 1);
10348 + var datapart = new Uint8Array(data.byteLength + 1);
10349 datapart.set(dataslice, 1); // Add a zero char at the start of the send, this will indicate that it's not a JSON command.
10350 files.send(datapart);
10351 } else {
@@ -10350,7 +10353,13 @@
10353 }
10354 uploadFile.xptr = end;
10355 Q('d2progressBar').value = end;
10353 - }
10356 + if (uploadFile.xptr >= uploadFile.xfile.size) {
10357 + files.sendText(JSON.stringify({ action: 'uploaddone', reqid: uploadFile.xfilePtr }));
10358 + } else {
10359 + if (uploadFile.xdataPriming > 0) { uploadFile.xdataPriming--; p13uploadNextPart(true); }
10360 + }
10361 + };
10362 + uploadFile.xreader.readAsArrayBuffer(uploadFile.xfile.slice(uploadFile.xptr, end));
10363 }
10364
10365 //