<?php /* * This file is part of Anis Server. * * (c) Laboratoire d'Astrophysique de Marseille / CNRS * * For the full copyright and license information, please view the LICENSE * file that was distributed with this source code. */ declare(strict_types=1); namespace App\Action; use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ResponseInterface; use Doctrine\ORM\EntityManagerInterface; use Slim\Exception\HttpNotFoundException; use Nyholm\Psr7\Factory\Psr17Factory; /** * @author François Agneray <francois.agneray@lam.fr> * @package App\Action */ final class DownloadArchiveAction extends AbstractAction { /** * Contains anis-server data path * * @var string */ private $dataPath; /** * Contains archive folder path * * @var string */ private $archiveFolder; /** * Contains settings to handle Json Web Token * * @var array */ private $settings; /** * Create the classe before call __invoke to execute the action * * @param EntityManagerInterface $em Doctrine Entity Manager Interface * @param string $dataPath Contains anis-server data path * @param string $archiveFolder Contains archive folder path * @param array $settings Settings about token */ public function __construct(EntityManagerInterface $em, string $dataPath, string $archiveFolder, array $settings) { parent::__construct($em); $this->dataPath = $dataPath; $this->archiveFolder = $archiveFolder; $this->settings = $settings; } /** * `GET` Returns the file found * * @param ServerRequestInterface $request PSR-7 This object represents the HTTP request * @param ResponseInterface $response PSR-7 This object represents the HTTP response * @param string[] $args This table contains information transmitted in the URL (see routes.php) * * @return ResponseInterface */ public function __invoke( ServerRequestInterface $request, ResponseInterface $response, array $args ): ResponseInterface { if ($request->getMethod() === OPTIONS) { return $response->withHeader('Access-Control-Allow-Methods', 'GET, OPTIONS'); } // Search the correct dataset with primary key $dataset = $this->em->find('App\Entity\Dataset', $args['dname']); // If dataset is not found 404 if (is_null($dataset)) { throw new HttpNotFoundException( $request, 'Dataset with name ' . $args['dname'] . ' is not found' ); } // If instance is private and authorization enabled $instance = $dataset->getDatasetFamily()->getInstance(); if (!$instance->getPublic() && boolval($this->settings['enabled'])) { $this->verifyInstanceAuthorization( $request, $instance->getName(), explode(',', $this->settings['admin_roles']) ); } // If dataset is private and authorization enabled if (!$dataset->getPublic() && boolval($this->settings['enabled'])) { $this->verifyDatasetAuthorization( $request, $dataset->getName(), explode(',', $this->settings['admin_roles']) ); } // Search the file $archiveId = $args['id']; $filePath = $this->dataPath . $this->archiveFolder . '/' . $archiveId . '.zip'; // If the file not found 404 if (!file_exists($filePath)) { throw new HttpNotFoundException( $request, 'Archive file with name ' . $archiveId . '.zip is not found' ); } // If the file found so stream it $psr17Factory = new Psr17Factory(); $stream = $psr17Factory->createStreamFromFile($filePath, 'r'); return $response->withBody($stream) ->withHeader('Content-Disposition', 'attachment; filename=' . basename($filePath) . ';') ->withHeader('Content-Type', mime_content_type($filePath)) ->withHeader('Content-Length', filesize($filePath)); } }