add up2k client code
This commit is contained in:
parent
1ac0b51c93
commit
11ad8a5c3b
@ -1,3 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
// error handler for mobile devices
|
// error handler for mobile devices
|
||||||
function hcroak(msg) {
|
function hcroak(msg) {
|
||||||
document.body.innerHTML = msg;
|
document.body.innerHTML = msg;
|
||||||
@ -61,12 +63,12 @@ function import_js(url, cb) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
function ebi(id) {
|
function o(id) {
|
||||||
return document.getElementById(id);
|
return document.getElementById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
function dbg(msg) {
|
function dbg(msg) {
|
||||||
ebi('path').innerHTML = msg;
|
o('path').innerHTML = msg;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -99,7 +101,7 @@ var mp = (function () {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (var a = 0, aa = tracks.length; a < aa; a++)
|
for (var a = 0, aa = tracks.length; a < aa; a++)
|
||||||
ebi('trk' + a).onclick = ev_play;
|
o('trk' + a).onclick = ev_play;
|
||||||
|
|
||||||
ret.vol = localStorage.getItem('vol');
|
ret.vol = localStorage.getItem('vol');
|
||||||
if (ret.vol !== null)
|
if (ret.vol !== null)
|
||||||
@ -156,7 +158,7 @@ var widget = (function () {
|
|||||||
ret.paused = function (paused) {
|
ret.paused = function (paused) {
|
||||||
if (was_paused != paused) {
|
if (was_paused != paused) {
|
||||||
was_paused = paused;
|
was_paused = paused;
|
||||||
ebi('bplay').innerHTML = paused ? '▶' : '⏸';
|
o('bplay').innerHTML = paused ? '▶' : '⏸';
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
var click_handler = function (e) {
|
var click_handler = function (e) {
|
||||||
@ -180,8 +182,8 @@ var widget = (function () {
|
|||||||
// buffer/position bar
|
// buffer/position bar
|
||||||
var pbar = (function () {
|
var pbar = (function () {
|
||||||
var r = {};
|
var r = {};
|
||||||
r.bcan = ebi('barbuf');
|
r.bcan = o('barbuf');
|
||||||
r.pcan = ebi('barpos');
|
r.pcan = o('barpos');
|
||||||
r.bctx = r.bcan.getContext('2d');
|
r.bctx = r.bcan.getContext('2d');
|
||||||
r.pctx = r.pcan.getContext('2d');
|
r.pctx = r.pcan.getContext('2d');
|
||||||
|
|
||||||
@ -246,7 +248,7 @@ var pbar = (function () {
|
|||||||
// volume bar
|
// volume bar
|
||||||
var vbar = (function () {
|
var vbar = (function () {
|
||||||
var r = {};
|
var r = {};
|
||||||
r.can = ebi('pvol');
|
r.can = o('pvol');
|
||||||
r.ctx = r.can.getContext('2d');
|
r.ctx = r.can.getContext('2d');
|
||||||
|
|
||||||
var bctx = r.ctx;
|
var bctx = r.ctx;
|
||||||
@ -343,7 +345,7 @@ var vbar = (function () {
|
|||||||
else
|
else
|
||||||
play(0);
|
play(0);
|
||||||
};
|
};
|
||||||
ebi('bplay').onclick = function (e) {
|
o('bplay').onclick = function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
if (mp.au) {
|
if (mp.au) {
|
||||||
if (mp.au.paused)
|
if (mp.au.paused)
|
||||||
@ -354,15 +356,15 @@ var vbar = (function () {
|
|||||||
else
|
else
|
||||||
play(0);
|
play(0);
|
||||||
};
|
};
|
||||||
ebi('bprev').onclick = function (e) {
|
o('bprev').onclick = function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
bskip(-1);
|
bskip(-1);
|
||||||
};
|
};
|
||||||
ebi('bnext').onclick = function (e) {
|
o('bnext').onclick = function (e) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
bskip(1);
|
bskip(1);
|
||||||
};
|
};
|
||||||
ebi('barpos').onclick = function (e) {
|
o('barpos').onclick = function (e) {
|
||||||
if (!mp.au) {
|
if (!mp.au) {
|
||||||
//dbg((new Date()).getTime());
|
//dbg((new Date()).getTime());
|
||||||
return play(0);
|
return play(0);
|
||||||
@ -437,7 +439,7 @@ function ev_play(e) {
|
|||||||
|
|
||||||
|
|
||||||
function setclass(id, clas) {
|
function setclass(id, clas) {
|
||||||
ebi(id).setAttribute('class', clas);
|
o(id).setAttribute('class', clas);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -569,7 +571,7 @@ function show_modal(html) {
|
|||||||
|
|
||||||
// hide fullscreen message
|
// hide fullscreen message
|
||||||
function unblocked() {
|
function unblocked() {
|
||||||
var dom = ebi('blocked');
|
var dom = o('blocked');
|
||||||
if (dom)
|
if (dom)
|
||||||
dom.remove();
|
dom.remove();
|
||||||
}
|
}
|
||||||
@ -585,8 +587,8 @@ function autoplay_blocked(tid) {
|
|||||||
<a id="blk_na">Cancel<br /><br />(show file list)</a>
|
<a id="blk_na">Cancel<br /><br />(show file list)</a>
|
||||||
</div>`);
|
</div>`);
|
||||||
|
|
||||||
var go = ebi('blk_go');
|
var go = o('blk_go');
|
||||||
var na = ebi('blk_na');
|
var na = o('blk_na');
|
||||||
|
|
||||||
var fn = mp.tracks[mp.au.tid].split(/\//).pop();
|
var fn = mp.tracks[mp.au.tid].split(/\//).pop();
|
||||||
fn = decodeURIComponent(fn.replace(/\+/g, ' '));
|
fn = decodeURIComponent(fn.replace(/\+/g, ' '));
|
||||||
|
@ -43,7 +43,7 @@
|
|||||||
<h5><input type="submit" value="start upload"></h5>
|
<h5><input type="submit" value="start upload"></h5>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<script src="/.cpr/splash.js"></script>
|
<!-- script src="/.cpr/splash.js"></script -->
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
@ -1,3 +1,5 @@
|
|||||||
|
"use strict";
|
||||||
|
|
||||||
// error handler for mobile devices
|
// error handler for mobile devices
|
||||||
function hcroak(msg) {
|
function hcroak(msg) {
|
||||||
document.body.innerHTML = msg;
|
document.body.innerHTML = msg;
|
||||||
@ -35,21 +37,538 @@ window.onerror = function (msg, url, lineNo, columnNo, error) {
|
|||||||
hcroak(html.join('\n'));
|
hcroak(html.join('\n'));
|
||||||
};
|
};
|
||||||
|
|
||||||
function ebi(id) {
|
function o(id) {
|
||||||
return document.getElementById(id);
|
return document.getElementById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
ebi('up2k').style.display = 'block';
|
(function () {
|
||||||
ebi('bup').style.display = 'none';
|
// hide basic uploader
|
||||||
|
o('up2k').style.display = 'block';
|
||||||
|
o('bup').style.display = 'none';
|
||||||
|
|
||||||
ebi('u2tgl').onclick = function (e) {
|
// upload ui hidden by default, clicking the header shows it
|
||||||
e.preventDefault();
|
o('u2tgl').onclick = function (e) {
|
||||||
ebi('u2tgl').style.display = 'none';
|
e.preventDefault();
|
||||||
ebi('u2body').style.display = 'block';
|
o('u2tgl').style.display = 'none';
|
||||||
}
|
o('u2body').style.display = 'block';
|
||||||
|
};
|
||||||
|
|
||||||
ebi('u2nope').onclick = function (e) {
|
// shows or clears an error message in the basic uploader ui
|
||||||
e.preventDefault();
|
function setmsg(msg) {
|
||||||
ebi('up2k').style.display = 'none';
|
if (msg !== undefined) {
|
||||||
ebi('bup').style.display = 'block';
|
o('u2err').setAttribute('class', 'err');
|
||||||
}
|
o('u2err').innerHTML = msg;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
o('u2err').setAttribute('class', '');
|
||||||
|
o('u2err').innerHTML = '';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// switches to the basic uploader with msg as error message
|
||||||
|
function un2k(msg) {
|
||||||
|
o('up2k').style.display = 'none';
|
||||||
|
o('bup').style.display = 'block';
|
||||||
|
setmsg(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
// handle user intent to use the basic uploader instead
|
||||||
|
o('u2nope').onclick = function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
un2k();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (!String.prototype.format) {
|
||||||
|
String.prototype.format = function () {
|
||||||
|
var args = arguments;
|
||||||
|
return this.replace(/{(\d+)}/g, function (match, number) {
|
||||||
|
return typeof args[number] != 'undefined' ?
|
||||||
|
args[number] : match;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
function cfg(name) {
|
||||||
|
var val = localStorage.getItem(name);
|
||||||
|
if (val === null)
|
||||||
|
return parseInt(o(name).value);
|
||||||
|
|
||||||
|
o(name).value = val
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parallel_uploads = cfg('nthread');
|
||||||
|
var chunksize_mb = cfg('chunksz');
|
||||||
|
var chunksize = chunksize_mb * 1024 * 1024;
|
||||||
|
|
||||||
|
var col_hashing = '#0099ff'; //'#d7d7d7';
|
||||||
|
//var col_hashed = '#e8a6df'; //'#decb7f';
|
||||||
|
//var col_hashed = '#0099ff';
|
||||||
|
var col_hashed = '#eeeeee';
|
||||||
|
var col_uploading = '#ffcc44';
|
||||||
|
var col_uploaded = '#00cc00';
|
||||||
|
var fdom_ctr = 0;
|
||||||
|
var st = {
|
||||||
|
"files": [],
|
||||||
|
"todo": {
|
||||||
|
"hash": [],
|
||||||
|
"handshake": [],
|
||||||
|
"upload": []
|
||||||
|
},
|
||||||
|
"busy": {
|
||||||
|
"hash": [],
|
||||||
|
"handshake": [],
|
||||||
|
"upload": []
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
var bobslice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
|
||||||
|
var have_crypto = window.crypto && crypto.subtle && crypto.subtle.digest;
|
||||||
|
|
||||||
|
if (!bobslice || !window.FileReader || !window.FileList || !have_crypto)
|
||||||
|
return un2k("this is the basic uploader; the good one needs at least<br />chrome 37 // firefox 34 // edge 12 // opera 24 // safari 7");
|
||||||
|
|
||||||
|
function nav() {
|
||||||
|
o('file' + fdom_ctr).click();
|
||||||
|
}
|
||||||
|
o('u2btn').addEventListener('click', nav, false);
|
||||||
|
|
||||||
|
function ondrag(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
ev.dataTransfer.dropEffect = 'copy';
|
||||||
|
ev.dataTransfer.effectAllowed = 'copy';
|
||||||
|
}
|
||||||
|
o('u2btn').addEventListener('dragover', ondrag, false);
|
||||||
|
o('u2btn').addEventListener('dragenter', ondrag, false);
|
||||||
|
|
||||||
|
function gotfile(ev) {
|
||||||
|
ev.stopPropagation();
|
||||||
|
ev.preventDefault();
|
||||||
|
|
||||||
|
var files = ev.dataTransfer ?
|
||||||
|
ev.dataTransfer.files : ev.target.files;
|
||||||
|
|
||||||
|
if (files.length == 0)
|
||||||
|
return alert('no files selected??');
|
||||||
|
|
||||||
|
more_one_file();
|
||||||
|
for (var a = 0; a < files.length; a++) {
|
||||||
|
var fobj = files[a];
|
||||||
|
var entry = {
|
||||||
|
"n": parseInt(st.files.length.toString()),
|
||||||
|
"fobj": fobj,
|
||||||
|
"name": fobj.name,
|
||||||
|
"size": fobj.size,
|
||||||
|
"hash": []
|
||||||
|
};
|
||||||
|
|
||||||
|
var skip = false;
|
||||||
|
for (var b = 0; b < st.files.length; b++)
|
||||||
|
if (entry.name == st.files[b].name &&
|
||||||
|
entry.size == st.files[b].size)
|
||||||
|
skip = true;
|
||||||
|
|
||||||
|
if (skip)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var tr = document.createElement('tr');
|
||||||
|
tr.innerHTML = '<td></td><td id="f{0}t">hashing</td><td id="f{0}p" class="prog"></td>'.format(st.files.length);
|
||||||
|
tr.getElementsByTagName('td')[0].textContent = entry.name;
|
||||||
|
o('u2tab').appendChild(tr);
|
||||||
|
|
||||||
|
st.files.push(entry);
|
||||||
|
st.todo.hash.push(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
o('u2btn').addEventListener('drop', gotfile, false);
|
||||||
|
|
||||||
|
function more_one_file() {
|
||||||
|
fdom_ctr++;
|
||||||
|
var elm = document.createElement('div')
|
||||||
|
elm.innerHTML = '<input id="file{0}" type="file" name="file{0}[]" multiple="multiple" />'.format(fdom_ctr);
|
||||||
|
o('u2form').appendChild(elm);
|
||||||
|
o('file' + fdom_ctr).addEventListener('change', gotfile, false);
|
||||||
|
}
|
||||||
|
more_one_file();
|
||||||
|
|
||||||
|
/////
|
||||||
|
////
|
||||||
|
/// actuator
|
||||||
|
//
|
||||||
|
|
||||||
|
function boss() {
|
||||||
|
if (st.todo.hash.length > 0 &&
|
||||||
|
st.busy.hash.length == 0)
|
||||||
|
exec_hash();
|
||||||
|
|
||||||
|
if (st.todo.handshake.length > 0 &&
|
||||||
|
st.busy.handshake.length == 0 &&
|
||||||
|
st.busy.upload.length < parallel_uploads)
|
||||||
|
exec_handshake();
|
||||||
|
|
||||||
|
if (st.todo.upload.length > 0 &&
|
||||||
|
st.busy.upload.length < parallel_uploads)
|
||||||
|
exec_upload();
|
||||||
|
|
||||||
|
setTimeout(boss, 100);
|
||||||
|
}
|
||||||
|
boss();
|
||||||
|
|
||||||
|
/////
|
||||||
|
////
|
||||||
|
/// hashing
|
||||||
|
//
|
||||||
|
|
||||||
|
// https://gist.github.com/jonleighton/958841
|
||||||
|
function buf2b64_maybe_fucky(buffer) {
|
||||||
|
var ret = '';
|
||||||
|
var view = new DataView(buffer);
|
||||||
|
for (var i = 0; i < view.byteLength; i++) {
|
||||||
|
ret += String.fromCharCode(view.getUint8(i));
|
||||||
|
}
|
||||||
|
return window.btoa(ret).replace(
|
||||||
|
/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://gist.github.com/jonleighton/958841
|
||||||
|
function buf2b64(arrayBuffer) {
|
||||||
|
var base64 = '';
|
||||||
|
var encodings = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_';
|
||||||
|
var bytes = new Uint8Array(arrayBuffer);
|
||||||
|
var byteLength = bytes.byteLength;
|
||||||
|
var byteRemainder = byteLength % 3;
|
||||||
|
var mainLength = byteLength - byteRemainder;
|
||||||
|
var a, b, c, d;
|
||||||
|
var chunk;
|
||||||
|
|
||||||
|
for (var i = 0; i < mainLength; i = i + 3) {
|
||||||
|
chunk = (bytes[i] << 16) | (bytes[i + 1] << 8) | bytes[i + 2];
|
||||||
|
// create 8*3=24bit segment then split into 6bit segments
|
||||||
|
a = (chunk & 16515072) >> 18; // 16515072 = (2^6 - 1) << 18
|
||||||
|
b = (chunk & 258048) >> 12; // 258048 = (2^6 - 1) << 12
|
||||||
|
c = (chunk & 4032) >> 6; // 4032 = (2^6 - 1) << 6
|
||||||
|
d = chunk & 63; // 63 = 2^6 - 1
|
||||||
|
|
||||||
|
// Convert the raw binary segments to the appropriate ASCII encoding
|
||||||
|
base64 += encodings[a] + encodings[b] + encodings[c] + encodings[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (byteRemainder == 1) {
|
||||||
|
chunk = bytes[mainLength];
|
||||||
|
a = (chunk & 252) >> 2; // 252 = (2^6 - 1) << 2
|
||||||
|
b = (chunk & 3) << 4; // 3 = 2^2 - 1 (zero 4 LSB)
|
||||||
|
base64 += encodings[a] + encodings[b];//+ '==';
|
||||||
|
}
|
||||||
|
else if (byteRemainder == 2) {
|
||||||
|
chunk = (bytes[mainLength] << 8) | bytes[mainLength + 1];
|
||||||
|
a = (chunk & 64512) >> 10; // 64512 = (2^6 - 1) << 10
|
||||||
|
b = (chunk & 1008) >> 4; // 1008 = (2^6 - 1) << 4
|
||||||
|
c = (chunk & 15) << 2; // 15 = 2^4 - 1 (zero 2 LSB)
|
||||||
|
base64 += encodings[a] + encodings[b] + encodings[c];//+ '=';
|
||||||
|
}
|
||||||
|
|
||||||
|
return base64;
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://developer.mozilla.org/en-US/docs/Web/API/SubtleCrypto/digest
|
||||||
|
function buf2hex(buffer) {
|
||||||
|
var hexCodes = [];
|
||||||
|
var view = new DataView(buffer);
|
||||||
|
for (var i = 0; i < view.byteLength; i += 4) {
|
||||||
|
var value = view.getUint32(i) // 4 bytes per iter
|
||||||
|
var stringValue = value.toString(16) // doesn't pad
|
||||||
|
var padding = '00000000'
|
||||||
|
var paddedValue = (padding + stringValue).slice(-padding.length)
|
||||||
|
hexCodes.push(paddedValue);
|
||||||
|
}
|
||||||
|
return hexCodes.join("");
|
||||||
|
}
|
||||||
|
|
||||||
|
function exec_hash() {
|
||||||
|
var t = st.todo.hash.shift();
|
||||||
|
st.busy.hash.push(t);
|
||||||
|
|
||||||
|
var nchunks = Math.ceil(t.size / chunksize);
|
||||||
|
var nchunk = 0;
|
||||||
|
|
||||||
|
var pb_html = '';
|
||||||
|
var pb_perc = 99.9 / nchunks;
|
||||||
|
for (var a = 0; a < nchunks; a++)
|
||||||
|
pb_html += '<div id="f{0}p{1}" style="width:{2}%"><div></div></div>'.format(
|
||||||
|
t.n, a, pb_perc);
|
||||||
|
|
||||||
|
o('f{0}p'.format(t.n)).innerHTML = pb_html;
|
||||||
|
|
||||||
|
var segm_next = function () {
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = segm_load;
|
||||||
|
reader.onerror = segm_err;
|
||||||
|
|
||||||
|
var car = nchunk * chunksize;
|
||||||
|
var cdr = car + chunksize;
|
||||||
|
if (cdr >= t.size)
|
||||||
|
cdr = t.size;
|
||||||
|
|
||||||
|
reader.readAsArrayBuffer(
|
||||||
|
bobslice.call(t.fobj, car, cdr));
|
||||||
|
|
||||||
|
prog(t.n, nchunk, col_hashing);
|
||||||
|
};
|
||||||
|
|
||||||
|
var segm_load = async function (ev) {
|
||||||
|
const hashbuf = await crypto.subtle.digest('SHA-256', ev.target.result);
|
||||||
|
t.hash.push(buf2b64(hashbuf));
|
||||||
|
|
||||||
|
prog(t.n, nchunk, col_hashed);
|
||||||
|
if (++nchunk < nchunks) {
|
||||||
|
prog(t.n, nchunk, col_hashing);
|
||||||
|
return segm_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
o('f{0}t'.format(t.n)).innerHTML = 'connecting';
|
||||||
|
st.busy.hash.splice(st.busy.hash.indexOf(t), 1);
|
||||||
|
st.todo.handshake.push(t);
|
||||||
|
};
|
||||||
|
|
||||||
|
var segm_err = function () {
|
||||||
|
alert('y o u b r o k e i t\n\n(was that a folder? just files please)');
|
||||||
|
};
|
||||||
|
|
||||||
|
segm_next();
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
////
|
||||||
|
/// handshake
|
||||||
|
//
|
||||||
|
|
||||||
|
function exec_handshake() {
|
||||||
|
var t = st.todo.handshake.shift();
|
||||||
|
st.busy.handshake.push(t);
|
||||||
|
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.onload = function (ev) {
|
||||||
|
if (xhr.status == 200) {
|
||||||
|
t.postlist = [];
|
||||||
|
t.wark = xhr.response.wark;
|
||||||
|
var missing = xhr.response.hash;
|
||||||
|
for (var a = 0; a < missing.length; a++) {
|
||||||
|
var idx = t.hash.indexOf(missing[a]);
|
||||||
|
if (idx < 0)
|
||||||
|
return alert('wtf negative index for hash "{0}" in task:\n{1}'.format(
|
||||||
|
missing[a], JSON.stringify(t)));
|
||||||
|
|
||||||
|
t.postlist.push(idx);
|
||||||
|
}
|
||||||
|
for (var a = 0; a < t.hash.length; a++)
|
||||||
|
prog(t.n, a, (t.postlist.indexOf(a) == -1)
|
||||||
|
? col_uploaded : col_hashed);
|
||||||
|
|
||||||
|
var msg = 'completed';
|
||||||
|
if (t.postlist.length > 0) {
|
||||||
|
for (var a = 0; a < t.postlist.length; a++)
|
||||||
|
st.todo.upload.push({
|
||||||
|
'nfile': t.n,
|
||||||
|
'npart': t.postlist[a]
|
||||||
|
});
|
||||||
|
|
||||||
|
msg = 'uploading';
|
||||||
|
}
|
||||||
|
o('f{0}t'.format(t.n)).innerHTML = msg;
|
||||||
|
st.busy.handshake.splice(st.busy.handshake.indexOf(t), 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alert("server broke (error {0}):\n\"{1}\"\n".format(
|
||||||
|
xhr.status, (xhr.response && xhr.response.err) ||
|
||||||
|
"no further information"));
|
||||||
|
};
|
||||||
|
xhr.open('POST', 'handshake.php', true);
|
||||||
|
xhr.responseType = 'json';
|
||||||
|
xhr.send(JSON.stringify({
|
||||||
|
"name": t.name,
|
||||||
|
"size": t.size,
|
||||||
|
"hash": t.hash
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
////
|
||||||
|
/// upload
|
||||||
|
//
|
||||||
|
|
||||||
|
function exec_upload() {
|
||||||
|
var upt = st.todo.upload.shift();
|
||||||
|
st.busy.upload.push(upt);
|
||||||
|
|
||||||
|
var npart = upt.npart;
|
||||||
|
var t = st.files[upt.nfile];
|
||||||
|
|
||||||
|
prog(t.n, npart, col_uploading);
|
||||||
|
|
||||||
|
var car = npart * chunksize;
|
||||||
|
var cdr = car + chunksize;
|
||||||
|
if (cdr >= t.size)
|
||||||
|
cdr = t.size;
|
||||||
|
|
||||||
|
var reader = new FileReader();
|
||||||
|
|
||||||
|
reader.onerror = function () {
|
||||||
|
alert('y o u b r o k e i t\n\n(was that a folder? just files please)');
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.onload = function (ev) {
|
||||||
|
var xhr = new XMLHttpRequest();
|
||||||
|
xhr.upload.onprogress = function (xev) {
|
||||||
|
var perc = xev.loaded / (cdr - car) * 100;
|
||||||
|
prog(t.n, npart, '', perc);
|
||||||
|
};
|
||||||
|
xhr.onload = function (xev) {
|
||||||
|
if (xhr.status == 200) {
|
||||||
|
prog(t.n, npart, col_uploaded);
|
||||||
|
st.busy.upload.splice(st.busy.upload.indexOf(upt), 1);
|
||||||
|
t.postlist.splice(t.postlist.indexOf(npart), 1);
|
||||||
|
if (t.postlist.length == 0) {
|
||||||
|
o('f{0}t'.format(t.n)).innerHTML = 'verifying';
|
||||||
|
st.todo.handshake.push(t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
alert("server broke (error {0}):\n\"{1}\"\n".format(
|
||||||
|
xhr.status, (xhr.response && xhr.response.err) ||
|
||||||
|
"no further information"));
|
||||||
|
};
|
||||||
|
xhr.open('POST', 'chunkpit.php', true);
|
||||||
|
//xhr.setRequestHeader("X-Up2k-Hash", t.hash[npart].substr(1) + "x");
|
||||||
|
xhr.setRequestHeader("X-Up2k-Hash", t.hash[npart]);
|
||||||
|
xhr.setRequestHeader("X-Up2k-Wark", t.wark);
|
||||||
|
xhr.setRequestHeader('Content-Type', 'application/octet-stream');
|
||||||
|
xhr.overrideMimeType('Content-Type', 'application/octet-stream');
|
||||||
|
xhr.responseType = 'json';
|
||||||
|
xhr.send(ev.target.result);
|
||||||
|
};
|
||||||
|
|
||||||
|
reader.readAsArrayBuffer(bobslice.call(t.fobj, car, cdr));
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
////
|
||||||
|
/// progress bar
|
||||||
|
//
|
||||||
|
|
||||||
|
function prog(nfile, nchunk, color, percent) {
|
||||||
|
var n1 = o('f{0}p{1}'.format(nfile, nchunk));
|
||||||
|
var n2 = n1.getElementsByTagName('div')[0];
|
||||||
|
if (percent === undefined) {
|
||||||
|
n1.style.background = color;
|
||||||
|
n2.style.display = 'none';
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
n2.style.width = percent + '%';
|
||||||
|
n2.style.display = 'block';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////
|
||||||
|
////
|
||||||
|
/// config ui
|
||||||
|
//
|
||||||
|
|
||||||
|
function bumpchunk(dir) {
|
||||||
|
try {
|
||||||
|
dir.stopPropagation();
|
||||||
|
dir.preventDefault();
|
||||||
|
} catch (ex) { }
|
||||||
|
|
||||||
|
if (st.files.length > 0)
|
||||||
|
return alert('only possible before you start uploading\n\n(refresh and try again)')
|
||||||
|
|
||||||
|
var obj = o('chunksz');
|
||||||
|
if (dir.target) {
|
||||||
|
obj.style.background = '#922';
|
||||||
|
var v = Math.floor(parseInt(obj.value));
|
||||||
|
if (v < 1 || v > 1024 || v !== v)
|
||||||
|
return;
|
||||||
|
|
||||||
|
chunksize_mb = v;
|
||||||
|
chunksize = chunksize_mb * 1024 * 1024;
|
||||||
|
localStorage.setItem('chunksz', v);
|
||||||
|
obj.style.background = '#444';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
chunksize_mb = Math.floor(chunksize_mb * dir);
|
||||||
|
|
||||||
|
if (chunksize_mb < 1)
|
||||||
|
chunksize_mb = 1;
|
||||||
|
|
||||||
|
if (chunksize_mb > 1024)
|
||||||
|
chunksize_mb = 1024;
|
||||||
|
|
||||||
|
obj.value = chunksize_mb;
|
||||||
|
bumpchunk({ "target": 1 })
|
||||||
|
}
|
||||||
|
|
||||||
|
function bumpthread(dir) {
|
||||||
|
try {
|
||||||
|
dir.stopPropagation();
|
||||||
|
dir.preventDefault();
|
||||||
|
} catch (ex) { }
|
||||||
|
|
||||||
|
var obj = o('nthread');
|
||||||
|
if (dir.target) {
|
||||||
|
obj.style.background = '#922';
|
||||||
|
var v = Math.floor(parseInt(obj.value));
|
||||||
|
if (v < 1 || v > 8 || v !== v)
|
||||||
|
return;
|
||||||
|
|
||||||
|
parallel_uploads = v;
|
||||||
|
localStorage.setItem('nthread', v);
|
||||||
|
obj.style.background = '#444';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
parallel_uploads += dir;
|
||||||
|
|
||||||
|
if (parallel_uploads < 1)
|
||||||
|
parallel_uploads = 1;
|
||||||
|
|
||||||
|
if (parallel_uploads > 8)
|
||||||
|
parallel_uploads = 8;
|
||||||
|
|
||||||
|
obj.value = parallel_uploads;
|
||||||
|
bumpthread({ "target": 1 })
|
||||||
|
}
|
||||||
|
|
||||||
|
function nop(ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
this.click();
|
||||||
|
}
|
||||||
|
|
||||||
|
o('chunksz_add').onclick = function (ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
bumpchunk(2);
|
||||||
|
};
|
||||||
|
o('chunksz_sub').onclick = function (ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
bumpchunk(0.5);
|
||||||
|
};
|
||||||
|
o('nthread_add').onclick = function (ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
bumpthread(1);
|
||||||
|
};
|
||||||
|
o('nthread_sub').onclick = function (ev) {
|
||||||
|
ev.preventDefault();
|
||||||
|
bumpthread(-1);
|
||||||
|
};
|
||||||
|
|
||||||
|
o('chunksz').addEventListener('input', bumpchunk, false);
|
||||||
|
o('nthread').addEventListener('input', bumpthread, false);
|
||||||
|
|
||||||
|
var nodes = o('u2conf').getElementsByTagName('a');
|
||||||
|
for (var a = nodes.length - 1; a >= 0; a--)
|
||||||
|
nodes[a].addEventListener('touchend', nop, false);
|
||||||
|
|
||||||
|
bumpchunk({ "target": 1 })
|
||||||
|
bumpthread({ "target": 1 })
|
||||||
|
})();
|
||||||
|
@ -2,7 +2,9 @@
|
|||||||
padding: .5em .5em .5em .3em;
|
padding: .5em .5em .5em .3em;
|
||||||
background: #2d2d2d;
|
background: #2d2d2d;
|
||||||
border-radius: 0 0 1em 0;
|
border-radius: 0 0 1em 0;
|
||||||
border-right: .3em solid #3a3a3a;
|
border: 1px solid #3a3a3a;
|
||||||
|
border-width: 0 .3em .3em 0;
|
||||||
|
box-shadow: 0 0 1em #222 inset;
|
||||||
max-width: 40em;
|
max-width: 40em;
|
||||||
}
|
}
|
||||||
#bup input {
|
#bup input {
|
||||||
@ -10,19 +12,19 @@
|
|||||||
}
|
}
|
||||||
#up2k {
|
#up2k {
|
||||||
display: none;
|
display: none;
|
||||||
|
padding: 1.5em 1em 0 1em;
|
||||||
|
}
|
||||||
|
#u2err.err {
|
||||||
|
color: #f87;
|
||||||
|
padding: .5em;
|
||||||
}
|
}
|
||||||
#u2tgl {
|
#u2tgl {
|
||||||
display: block;
|
|
||||||
color: #fc5;
|
color: #fc5;
|
||||||
background: #444;
|
|
||||||
width: 14em;
|
|
||||||
font-size: 1.5em;
|
font-size: 1.5em;
|
||||||
padding: 1em 1em .25em 1em;
|
|
||||||
border-bottom: 2px solid #2c2c2c;
|
|
||||||
border-radius: 0 0 .3em 0;
|
|
||||||
}
|
}
|
||||||
#u2body {
|
#u2body {
|
||||||
display: none;
|
display: none;
|
||||||
|
padding-bottom: 2em;
|
||||||
}
|
}
|
||||||
#u2form {
|
#u2form {
|
||||||
width: 2px;
|
width: 2px;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
<div id="bup">
|
<div id="bup">
|
||||||
|
<div id="u2err"></div>
|
||||||
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="/{{ vdir }}">
|
<form method="post" enctype="multipart/form-data" accept-charset="utf-8" action="/{{ vdir }}">
|
||||||
<input type="hidden" name="act" value="bput" />
|
<input type="hidden" name="act" value="bput" />
|
||||||
<input type="file" name="f" multiple><br />
|
<input type="file" name="f" multiple><br />
|
||||||
@ -7,9 +8,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="up2k">
|
<div id="up2k">
|
||||||
|
<a href="#" id="u2tgl">you can upload here</a>
|
||||||
<a href="#" id="u2tgl">upload</a>
|
|
||||||
|
|
||||||
<div id="u2body">
|
<div id="u2body">
|
||||||
<form id="u2form" method="POST" enctype="multipart/form-data" onsubmit="return false;"></form>
|
<form id="u2form" method="POST" enctype="multipart/form-data" onsubmit="return false;"></form>
|
||||||
|
|
||||||
@ -20,14 +19,14 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" onclick="nthread_sub()">–</a>
|
<a href="#" id="nthread_sub">–</a>
|
||||||
<input id="nthread" value="2" />
|
<input id="nthread" value="2" />
|
||||||
<a href="#" onclick="nthread_add()">+</a>
|
<a href="#" id="nthread_add">+</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a href="#" onclick="chunksz_sub()">–</a>
|
<a href="#" id="chunksz_sub">–</a>
|
||||||
<input id="chunksz" value="8" />
|
<input id="chunksz" value="8" />
|
||||||
<a href="#" onclick="chunksz_add()">+</a>
|
<a href="#" id="chunksz_add">+</a>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
@ -45,6 +44,6 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
switch to the <a href="#" id="u2nope">basic uploader</a>
|
switch to the <a href="#" id="u2nope">basic uploader</a> if you don't need resumable uploads and progress bars
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user