perf: Optimize downloading directories as zip to avoid counting files for zip64

Signed-off-by: Julius Knorr <jus@bitgrid.net>
This commit is contained in:
Julius Knorr 2025-10-31 12:57:50 +01:00
parent a459f56184
commit d861c1da3b
No known key found for this signature in database
GPG key ID: 4C614C6ED2CDE6DF
2 changed files with 7 additions and 10 deletions

View file

@ -150,13 +150,6 @@ class ZipFolderPlugin extends ServerPlugin {
throw new Forbidden($errorMessage);
}
$content = empty($files) ? $folder->getDirectoryListing() : [];
foreach ($files as $path) {
$child = $node->getChild($path);
assert($child instanceof Node);
$content[] = $child->getNode();
}
$archiveName = $folder->getName();
if (count(explode('/', trim($folder->getPath(), '/'), 3)) === 2) {
// this is a download of the root folder
@ -169,13 +162,17 @@ class ZipFolderPlugin extends ServerPlugin {
$rootPath = dirname($folder->getPath());
}
$streamer = new Streamer($tarRequest, -1, count($content), $this->timezoneFactory);
$streamer = new Streamer($tarRequest, -1, -1, $this->timezoneFactory);
$streamer->sendHeaders($archiveName);
// For full folder downloads we also add the folder itself to the archive
if (empty($files)) {
$streamer->addEmptyDir($archiveName);
}
$content = empty($files) ? $folder->getDirectoryListing() : array_map(fn (string $path) => $folder->get($path), $files);
foreach ($content as $node) {
assert($node instanceof NcNode);
$this->streamNode($streamer, $node, $rootPath);
}
$streamer->finalize();

View file

@ -39,7 +39,7 @@ class Streamer {
* please migrate to `Streamer::isUserAgentPreferTar()` instead.
* @param int|float $size The size of the files in bytes
* @param int $numberOfFiles The number of files (and directories) that will
* be included in the streamed file
* be included in the streamed file, used to detect if zip32 or zip64 should be used, can be set to -1 to enforce zip64
*/
public function __construct(
IRequest|bool $preferTar,
@ -80,7 +80,7 @@ class Streamer {
if ($preferTar) {
// If TAR ball is preferred use it
$this->streamerInstance = new TarStreamer();
} elseif ($size > 0 && $size < 4 * 1000 * 1000 * 1000 && $numberOfFiles < 65536) {
} elseif ($size > 0 && $size < 4 * 1000 * 1000 * 1000 && $numberOfFiles < 65536 && $numberOfFiles >= 0) {
$this->streamerInstance = new ZipStreamer(['zip64' => false]);
} else {
$this->streamerInstance = new ZipStreamer(['zip64' => true]);