up2k: u2sz: allow 1 as max + detect http413

This commit is contained in:
ed 2026-08-15 09:45:13 +00:00
parent 8b6e8972fe
commit f19ef033ec
7 changed files with 61 additions and 19 deletions

View file

@ -84,6 +84,7 @@ built in Norway 🇳🇴 with contributions from [not-norway](https://github.com
* [exclude-patterns](#exclude-patterns) - to save some time
* [filesystem guards](#filesystem-guards) - avoid traversing into other filesystems
* [periodic rescan](#periodic-rescan) - filesystem monitoring
* [u2sz](#u2sz) - configure upload-chunking
* [upload rules](#upload-rules) - set upload rules using volflags
* [compress uploads](#compress-uploads) - files can be autocompressed on upload
* [chmod and chown](#chmod-and-chown) - per-volume filesystem-permissions and ownership
@ -922,7 +923,7 @@ note that since up2k has to read each file twice, `[🎈] bup` can *theoreticall
if you are resuming a massive upload and want to skip hashing the files which already finished, you can enable `turbo` in the `[⚙️] config` tab, but please read the tooltip on that button
if the server is behind a proxy which imposes a request-size limit, you can configure up2k to sneak below the limit with server-option `--u2sz` (the default is 96 MiB to support Cloudflare)
if the server is behind a proxy which imposes a request-size limit, you can configure up2k to sneak below the limit with server-option [--u2sz](#u2sz)
if you want to replace existing files on the server with new uploads by default, run with `--u2ow 2` (only works if users have the delete-permission, and can still be disabled with `🛡️` in the UI)
@ -1826,6 +1827,23 @@ config file example:
```
## u2sz
configure upload-chunking; the default `64,96` is optimal for nearly every scenario, however:
* if you are seeing the message `bad server config; see "u2sz" in readme` then you have a proxy/CDN/whatever with a `max-request-body-size` which is too small, and you must either increase the limit in the reverseproxy config to at least 96 MiB (recommended) or reduce the target chunksize in copyparty (continue reading)
the global-option `--u2sz` is two numbers, `target,max` MiB of each chunk to send, aiming for `target` MiB and allowing up-to-and-including `max` MiB [depending on filesize](./docs/devnotes.md#list-of-chunk-sizes), and if you only specify one number then it sets that for both
cloudflare max is 96 MiB, but if you have a reverseproxy (or CDN/WAF/whatever) which is more restrictive, then try some of the following:
* `u2sz: 32` is still acceptable performance in most cases
* `u2sz: 8` is the lowest recommended value; anything lower will reduce performance over long physical distances and/or shitty routes
* `u2sz: 1` is the absolute minimum, and will be slow in many cases
the setting can also be changed in the web-UI; the textbox next to `date-chk` in the settings tab
## upload rules
set upload rules using volflags, some examples:

View file

@ -1338,7 +1338,7 @@ def add_upload(ap):
ap2.add_argument("--turbo", metavar="LVL", type=int, default=0, help="configure turbo-mode in up2k client; [\033[32m-1\033[0m] = forbidden/always-off, [\033[32m0\033[0m] = default-off and warn if enabled, [\033[32m1\033[0m] = default-off, [\033[32m2\033[0m] = on, [\033[32m3\033[0m] = on and disable datecheck")
ap2.add_argument("--nosubtle", metavar="N", type=int, default=0, help="when to use a wasm-hasher instead of the browser's builtin; faster on chrome, but buggy in older chrome versions. [\033[32m0\033[0m] = only when necessary (non-https), [\033[32m1\033[0m] = always (all browsers), [\033[32m2\033[0m] = always on chrome/firefox, [\033[32m3\033[0m] = always on chrome, [\033[32mN\033[0m] = chrome-version N and newer (recommendation: 137)")
ap2.add_argument("--u2j", metavar="JOBS", type=int, default=2, help="web-client: number of file chunks to upload in parallel; 1 or 2 is good when latency is low (same-country), 2~4 for android-clients, 2~6 for cross-atlantic. Max is 6 in most browsers. Big values increase network-speed but may reduce HDD-speed")
ap2.add_argument("--u2sz", metavar="N,N,N", type=u, default="1,64,96", help="web-client: default upload chunksize (MiB); sets \033[33mmin,default,max\033[0m in the settings gui. Each HTTP POST will aim for \033[33mdefault\033[0m, and never exceed \033[33mmax\033[0m. Cloudflare max is 96. Big values are good for cross-atlantic but may increase HDD fragmentation on some FS. Disable this optimization with [\033[32m1,1,1\033[0m]")
ap2.add_argument("--u2sz", metavar="N,N", type=u, default="64,96", help="web-client: default upload chunksize in MiB, either \033[33mtarget,max\033[0m or just \033[33mtarget\033[0m (sets both); this is \033[33mtarget\033[0m in the web-UI. Each HTTP POST will aim for \033[33mtarget\033[0m and never exceed \033[33mmax\033[0m. Cloudflare max is 96. Minimum is [\033[32m1\033[0m] and will be slow. Lowest recommended is [\033[32m8\033[0m]. Big values are good for cross-atlantic but may increase HDD fragmentation on some FS. Disable this optimization with [\033[32mno\033[0m]")
ap2.add_argument("--u2ow", metavar="NUM", type=int, default=0, help="web-client: default setting for when to replace/overwrite existing files; [\033[32m0\033[0m]=never, [\033[32m1\033[0m]=if-client-newer, [\033[32m2\033[0m]=always (volflag=u2ow)")
ap2.add_argument("--u2sort", metavar="TXT", type=u, default="s", help="upload order; [\033[32ms\033[0m]=smallest-first, [\033[32mn\033[0m]=alphabetical, [\033[32mfs\033[0m]=force-s, [\033[32mfn\033[0m]=force-n -- alphabetical is a bit slower on fiber/LAN but makes it easier to eyeball if everything went fine")
ap2.add_argument("--write-uplog", action="store_true", help="write POST reports to textfiles in working-directory")

View file

@ -1383,18 +1383,20 @@ class SvcHub(object):
self.args.name_html = zs
zs = al.u2sz
if zs in ("no", "1,1,1"):
zs = "0"
zsl = [x.strip() for x in zs.split(",")]
if len(zsl) not in (1, 3):
t = "invalid --u2sz; must be either one number, or a comma-separated list of three numbers (min,default,max)"
if len(zsl) not in (1, 2):
t = "invalid --u2sz; must be either one number, or a comma-separated list of two numbers (target,max)"
raise Exception(t)
if len(zsl) < 3:
zsl = ["1", zs, zs]
zi2 = 1
if len(zsl) < 2:
zsl = [zs, zs]
zi2 = 0
for zs in zsl:
zi = int(zs)
# arbitrary constraint (anything above 2 GiB is probably unintended)
if zi < 1 or zi > 2047:
raise Exception("invalid --u2sz; minimum is 1, max is 2047")
if zi < 0 or zi > 2047:
raise Exception("invalid --u2sz; minimum is 0, max is 2047")
if zi < zi2:
raise Exception("invalid --u2sz; values must be equal or ascending")
zi2 = zi

View file

@ -758,7 +758,7 @@ if (window.glang && navigator.languages && !/\bcplng=/.test(document.cookie))
if (window.stop)
window.stop();
document.body.innerHTML = 'Loading ' + n;
setck("cplng=" + n, location.reload.bind(location));
setck("cplng=" + n, relod);
crashed = true;
throw 1;
}
@ -8626,7 +8626,7 @@ var setfszf = (function () {
setck('cplng=' + lang);
freshen();
var t = L.tt == 'English' ? '' : Ls.eng.lang_set;
modal.confirm(L.lang_set + "\n\n" + t, location.reload.bind(location), null);
modal.confirm(L.lang_set + "\n\n" + t, relod, null);
}
freshen();

View file

@ -325,6 +325,9 @@ var modpoll = new Modpoll();
window.onbeforeunload = function (e) {
if (window.gtfo)
return;
if ((ebi("save").className + '').indexOf('disabled') >= 0)
return; //nice (todo)

View file

@ -888,9 +888,8 @@ function up2k_init(subtle) {
setmsg(suggest_up2k, 'msg');
var u2szs = u2sz.split(','),
u2sz_min = parseInt(u2szs[0]),
u2sz_tgt = parseInt(u2szs[1]),
u2sz_max = parseInt(u2szs[2]);
u2sz_tgt = parseInt(u2szs[0]),
u2sz_max = parseInt(u2szs[1]);
var parallel_uploads = ebi('nthread').value = icfg_get('nthread', u2j),
stitch_tgt = ebi('u2szg').value = icfg_get('u2sz', u2sz_tgt),
@ -2677,7 +2676,7 @@ function up2k_init(subtle) {
ccs += stp; stp *= 2;
}
ocs = Math.floor(ocs / 1024 / 1024);
t.stitch_sz = Math.min(ocs, stitch_tgt);
t.stitch_sz = Math.min(ocs, stitch_tgt || 1);
}
for (var a = 0; a < t.postlist.length; a++) {
@ -2879,7 +2878,8 @@ function up2k_init(subtle) {
nparts = upt.nparts,
pcar = nparts[0],
pcdr = nparts[nparts.length - 1],
maxsz = (u2sz_max > 1 ? u2sz_max : 2040) * 1024 * 1024;
maxmsz = stitch_tgt == u2sz_tgt ? u2sz_max : stitch_tgt,
maxsz = (maxmsz > 0 ? maxmsz : 2040) * 1024 * 1024;
if (t.done)
return console.log('done; skip chunk', t.name, t);
@ -2951,6 +2951,9 @@ function up2k_init(subtle) {
st.etac.u++;
st.etac.t++;
}
else if (xhr.status == 413) {
modal.die('bad server config; see "u2sz" in readme');
}
else if (txt.indexOf('already got that') + 1) {
unqueue_up(t);
}
@ -3163,7 +3166,7 @@ function up2k_init(subtle) {
var el = ebi('u2szg'), n = parseInt(el.value);
stitch_tgt = n = (
isNaN(n) ? u2sz_tgt :
n < u2sz_min ? u2sz_min :
n < 0 ? 0 :
n > u2sz_max ? u2sz_max : n
);
if (n == u2sz_tgt) sdrop('u2sz'); else swrite('u2sz', n);
@ -3400,7 +3403,7 @@ function up2k_init(subtle) {
function set_nosubtle(v) {
if (!WebAssembly)
return toast.err(10, L.u_nowork);
modal.confirm(L.lang_set, location.reload.bind(location), null);
modal.confirm(L.lang_set, relod, null);
}
function set_upnag(en) {
@ -3471,6 +3474,9 @@ function up2k_init(subtle) {
function warn_uploader_busy(e) {
if (window.gtfo)
return;
e.preventDefault();
e.returnValue = '';
return "upload in progress, click abort and use the file-tree to navigate instead";

View file

@ -108,6 +108,13 @@ function qsr(sel) {
}
function relod() {
crashed = 1;
window.gtfo = 1;
location.href = location.href;
}
// error handler for mobile devices
function esc(txt) {
return txt.replace(/[&"<>]/g, function (c) {
@ -289,7 +296,7 @@ function vis_exh(msg, url, lineNo, columnNo, error) {
var x = ebi('exh_wipecfg');
if (x) x.onclick = function () {
localStorage.clear();
location.reload();
relod();
};
x = ebi('exh_ignex'); if (x) x.onclick = ignex;
x = ebi('exh_ignexa'); if (x) x.onclick = ignexa;
@ -2021,6 +2028,12 @@ var modal = (function () {
q.shift()();
}
r.die = function (html) {
crashed = 1;
if (r.busy)
r.hide();
_alert(lf2br(html), relod);
};
r.alert = function (html, cb, fun) {
q.push(function () {
_alert(lf2br(html), cb, fun);