Clean up tar process handling; make stdout non-blocking.

This commit is contained in:
Aaron van Geffen 2020-03-11 12:13:04 +01:00
parent 2bb29d7224
commit 5a51778a6a

View File

@ -34,7 +34,7 @@ class Download
$files = []; $files = [];
$album_ids = array_merge([$album->id_tag], $this->getChildAlbumIds($album->id_tag)); $album_ids = array_merge([$album->id_tag], $this->getChildAlbumIds($album->id_tag));
foreach($album_ids as $album_id) foreach ($album_ids as $album_id)
{ {
$iterator = AssetIterator::getByOptions(['id_tag' => $album_id]); $iterator = AssetIterator::getByOptions(['id_tag' => $album_id]);
while ($asset = $iterator->next()) while ($asset = $iterator->next())
@ -42,8 +42,8 @@ class Download
} }
$descriptorspec = [ $descriptorspec = [
0 => ['pipe', 'r'], 0 => ['pipe', 'r'], // STDIN
1 => ['pipe', 'w'], 1 => ['pipe', 'w'], // STDOUT
]; ];
$command = 'tar -cf - -C ' . escapeshellarg(ASSETSDIR) . ' --null -T -'; $command = 'tar -cf - -C ' . escapeshellarg(ASSETSDIR) . ' --null -T -';
@ -59,22 +59,33 @@ class Download
if(!$pipes[1]) if(!$pipes[1])
throw new UnexpectedValueException('Could not open pipe for STDOUT'); throw new UnexpectedValueException('Could not open pipe for STDOUT');
$album_name = $album->tag; // STDOUT should not block.
stream_set_blocking($pipes[1], 0);
header('Pragma: no-cache'); header('Pragma: no-cache');
header('Content-Description: File Download'); header('Content-Description: File Download');
header('Content-disposition: attachment; filename="' . $album_name . '.tar"'); header('Content-disposition: attachment; filename="' . $album->tag . '.tar"');
header('Content-Type: application/octet-stream'); header('Content-Type: application/octet-stream');
header('Content-Transfer-Encoding: binary'); header('Content-Transfer-Encoding: binary');
foreach($files as $file) // Write filenames to include to STDIN, separated by null bytes.
foreach ($files as $file)
fwrite($pipes[0], $file . "\0"); fwrite($pipes[0], $file . "\0");
// Close STDIN pipe to start archiving.
fclose($pipes[0]); fclose($pipes[0]);
while($chunk = stream_get_contents($pipes[1], 4096)) do
echo $chunk; {
// Read STDOUT as `tar` is doing its work.
echo stream_get_contents($pipes[1], 4096);
// Are we still running?
$status = proc_get_status($proc);
}
while (!empty($status) && $status['running']);
// Close STDOUT pipe and clean up process.
fclose($pipes[1]); fclose($pipes[1]);
proc_close($proc); proc_close($proc);