123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102 |
- <?php
- namespace Drupal\system;
- use Drupal\Core\Controller\ControllerBase;
- use Drupal\Core\StreamWrapper\StreamWrapperManagerInterface;
- use Symfony\Component\DependencyInjection\ContainerInterface;
- use Symfony\Component\HttpFoundation\BinaryFileResponse;
- use Symfony\Component\HttpFoundation\Request;
- use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
- use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
- /**
- * System file controller.
- */
- class FileDownloadController extends ControllerBase {
- /**
- * The stream wrapper manager.
- *
- * @var \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface
- */
- protected $streamWrapperManager;
- /**
- * FileDownloadController constructor.
- *
- * @param \Drupal\Core\StreamWrapper\StreamWrapperManagerInterface $streamWrapperManager
- * The stream wrapper manager.
- */
- public function __construct(StreamWrapperManagerInterface $streamWrapperManager = NULL) {
- if (!$streamWrapperManager) {
- @trigger_error('Calling FileDownloadController::__construct() without the $streamWrapperManager argument is deprecated in drupal:8.8.0. The $streamWrapperManager argument will be required in drupal:9.0.0. See https://www.drupal.org/node/3035273', E_USER_DEPRECATED);
- $streamWrapperManager = \Drupal::service('stream_wrapper_manager');
- }
- $this->streamWrapperManager = $streamWrapperManager;
- }
- /**
- * {@inheritdoc}
- */
- public static function create(ContainerInterface $container) {
- return new static(
- $container->get('stream_wrapper_manager')
- );
- }
- /**
- * Handles private file transfers.
- *
- * Call modules that implement hook_file_download() to find out if a file is
- * accessible and what headers it should be transferred with. If one or more
- * modules returned headers the download will start with the returned headers.
- * If a module returns -1 an AccessDeniedHttpException will be thrown. If the
- * file exists but no modules responded an AccessDeniedHttpException will be
- * thrown. If the file does not exist a NotFoundHttpException will be thrown.
- *
- * @see hook_file_download()
- *
- * @param \Symfony\Component\HttpFoundation\Request $request
- * The request object.
- * @param string $scheme
- * The file scheme, defaults to 'private'.
- *
- * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
- * The transferred file as response.
- *
- * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
- * Thrown when the requested file does not exist.
- * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
- * Thrown when the user does not have access to the file.
- */
- public function download(Request $request, $scheme = 'private') {
- $target = $request->query->get('file');
- // Merge remaining path arguments into relative file path.
- $uri = $scheme . '://' . $target;
- if ($this->streamWrapperManager->isValidScheme($scheme) && is_file($uri)) {
- // Let other modules provide headers and controls access to the file.
- $headers = $this->moduleHandler()->invokeAll('file_download', [$uri]);
- foreach ($headers as $result) {
- if ($result == -1) {
- throw new AccessDeniedHttpException();
- }
- }
- if (count($headers)) {
- // \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
- // sets response as not cacheable if the Cache-Control header is not
- // already modified. We pass in FALSE for non-private schemes for the
- // $public parameter to make sure we don't change the headers.
- return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
- }
- throw new AccessDeniedHttpException();
- }
- throw new NotFoundHttpException();
- }
- }
|