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
//