2015-08-18 00:00:26 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
namespace Drupal\system;
|
|
|
|
|
|
|
|
use Drupal\Core\Controller\ControllerBase;
|
|
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
|
|
use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
|
|
|
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
|
|
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* System file controller.
|
|
|
|
*/
|
|
|
|
class FileDownloadController extends ControllerBase {
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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'.
|
|
|
|
*
|
2015-11-04 19:11:27 +00:00
|
|
|
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
|
|
|
* The transferred file as response.
|
|
|
|
*
|
2015-08-18 00:00:26 +00:00
|
|
|
* @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 (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
|
|
|
|
// Let other modules provide headers and controls access to the file.
|
2017-04-13 14:53:35 +00:00
|
|
|
$headers = $this->moduleHandler()->invokeAll('file_download', [$uri]);
|
2015-08-18 00:00:26 +00:00
|
|
|
|
|
|
|
foreach ($headers as $result) {
|
|
|
|
if ($result == -1) {
|
|
|
|
throw new AccessDeniedHttpException();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (count($headers)) {
|
2015-10-08 18:40:12 +00:00
|
|
|
// \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');
|
2015-08-18 00:00:26 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
throw new AccessDeniedHttpException();
|
|
|
|
}
|
|
|
|
|
|
|
|
throw new NotFoundHttpException();
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|