mirror of
https://github.com/9001/copyparty.git
synced 2026-06-18 20:22:27 -06:00
download-as-zip: toplevel optional
This commit is contained in:
parent
c28aa08b35
commit
cc5420a324
|
|
@ -836,6 +836,7 @@ you can also zip a selection of files or folders by clicking them in the browser
|
|||
|
||||
cool trick: download a folder by appending url-params `?tar&opus` or `?tar&mp3` to transcode all audio files (except aac|m4a|mp3|ogg|opus|wma) to opus/mp3 before they're added to the archive
|
||||
* super useful if you're 5 minutes away from takeoff and realize you don't have any music on your phone but your server only has flac files and downloading those will burn through all your data + there wouldn't be enough time anyways
|
||||
* and url-param `&name=foo` changes the name of the toplevel folder in the archive to `foo`, and just `&name` removes the folder entirely
|
||||
* and url-param `&nodot` skips dotfiles/dotfolders; they are included by default if your account has permission to see them
|
||||
* and url-params `&j` / `&w` produce jpeg/webm thumbnails/spectrograms instead of the original audio/video/images (`&p` for audio waveforms)
|
||||
* can also be used to pregenerate thumbnails; combine with `--th-maxage=9999999` or `--th-clean=0`
|
||||
|
|
|
|||
|
|
@ -900,20 +900,14 @@ class VFS(object):
|
|||
|
||||
def zipgen(
|
||||
self,
|
||||
vpath: str,
|
||||
folder: str,
|
||||
vrem: str,
|
||||
flt: set[str],
|
||||
uname: str,
|
||||
dirs: bool,
|
||||
dots: int,
|
||||
scandir: bool,
|
||||
wrap: bool = True,
|
||||
) -> Generator[dict[str, Any], None, None]:
|
||||
|
||||
# if multiselect: add all items to archive root
|
||||
# if single folder: the folder itself is the top-level item
|
||||
folder = "" if flt or not wrap else (vpath.split("/")[-1].lstrip(".") or "top")
|
||||
|
||||
g = self.walk(folder, vrem, [], uname, [[True, False]], dots, scandir, False)
|
||||
for _, _, vpath, apath, files, rd, vd in g:
|
||||
if flt:
|
||||
|
|
|
|||
|
|
@ -1823,14 +1823,13 @@ class HttpCli(object):
|
|||
# because lstat=true would not recurse into subfolders
|
||||
# and this is a rare case where we actually want that
|
||||
fgen = vn.zipgen(
|
||||
rem,
|
||||
"",
|
||||
rem,
|
||||
set(),
|
||||
self.uname,
|
||||
True,
|
||||
1,
|
||||
not self.args.no_scandir,
|
||||
wrap=False,
|
||||
)
|
||||
|
||||
elif depth == "0":
|
||||
|
|
@ -5163,6 +5162,16 @@ class HttpCli(object):
|
|||
if items:
|
||||
fn = "sel-" + fn
|
||||
|
||||
if "name" in self.ouparam:
|
||||
# user-selected name for toplevel folder, or blank for none
|
||||
vpath = undot(self.ouparam["name"])
|
||||
elif items:
|
||||
# multiselect; add all items to archive root
|
||||
vpath = ""
|
||||
else:
|
||||
# single folder; the folder itself is the top-level item
|
||||
vpath = vpath.split("/")[-1].lstrip(".") or "top"
|
||||
|
||||
if vn.flags.get("zipmax") and not (
|
||||
vn.flags.get("zipmaxu") and self.uname != "*"
|
||||
):
|
||||
|
|
@ -5209,7 +5218,7 @@ class HttpCli(object):
|
|||
|
||||
if cfmt:
|
||||
self.log("transcoding to [{}]".format(cfmt))
|
||||
fgen = gfilter(fgen, self.thumbcli, self.uname, vpath, cfmt)
|
||||
fgen = gfilter(fgen, self.thumbcli, self.uname, self.vpath, vpath, cfmt)
|
||||
|
||||
now = time.time()
|
||||
self.dl_id = "%s:%s" % (self.ip, self.addr[1])
|
||||
|
|
|
|||
|
|
@ -700,7 +700,7 @@ class HttpSrv(object):
|
|||
if not fmts:
|
||||
continue
|
||||
log("starting for volume /%s" % (vn.vpath,), 6)
|
||||
g = vn.walk("x", "/", [], LEELOO_DALLAS, [[True]], 2, scandir, False, False)
|
||||
g = vn.walk("", "/", [], LEELOO_DALLAS, [[True]], 2, scandir, False, False)
|
||||
g = gfilter2(g, self, vn.vpath, fmts.split(","))
|
||||
for f in g:
|
||||
nfiles += 1
|
||||
|
|
|
|||
|
|
@ -61,6 +61,7 @@ def gfilter(
|
|||
thumbcli: ThumbCli,
|
||||
uname: str,
|
||||
vtop: str,
|
||||
vname: str,
|
||||
fmt: str,
|
||||
) -> Generator[dict[str, Any], None, None]:
|
||||
from concurrent.futures import ThreadPoolExecutor
|
||||
|
|
@ -70,7 +71,7 @@ def gfilter(
|
|||
_pools[tp] = 1
|
||||
try:
|
||||
for f in fgen:
|
||||
task = tp.submit(enthumb, thumbcli, uname, vtop, f, fmt)
|
||||
task = tp.submit(enthumb, thumbcli, uname, vtop, vname, f, fmt)
|
||||
pend.append((task, f))
|
||||
if pend[0][0].done() or len(pend) > CORES * 4:
|
||||
task, f = pend.pop(0)
|
||||
|
|
@ -130,7 +131,7 @@ def gfilter2(
|
|||
try:
|
||||
f = {"vp": vp, "st": fi[1]}
|
||||
task = tp.submit(
|
||||
enthumb, hsrv.thumbcli, LEELOO_DALLAS, vtop, f, fmt
|
||||
enthumb, hsrv.thumbcli, LEELOO_DALLAS, vtop, "", f, fmt
|
||||
)
|
||||
pend.append((task, f))
|
||||
if pend[0][0].done() or len(pend) > CORES * 4:
|
||||
|
|
@ -152,14 +153,17 @@ def gfilter2(
|
|||
|
||||
|
||||
def enthumb(
|
||||
thumbcli: ThumbCli, uname: str, vtop: str, f: dict[str, Any], fmt: str
|
||||
thumbcli: ThumbCli, uname: str, vtop: str, vname: str, f: dict[str, Any], fmt: str
|
||||
) -> dict[str, Any]:
|
||||
rem = f["vp"]
|
||||
ext = rem.rsplit(".", 1)[-1].lower()
|
||||
if (fmt == "mp3" and ext == "mp3") or (fmt == "opus" and ext in TAR_NO_OPUS):
|
||||
raise Exception()
|
||||
|
||||
if vname:
|
||||
vp = vjoin(vtop, rem.split("/", 1)[1])
|
||||
else:
|
||||
vp = vjoin(vtop, rem)
|
||||
vn, rem = thumbcli.asrv.vfs.get(vp, uname, True, False)
|
||||
dbv, vrem = vn.get_dbv(rem)
|
||||
thp = thumbcli.get(dbv, vrem, f["st"].st_mtime, fmt)
|
||||
|
|
|
|||
Loading…
Reference in a new issue