Chris@0
|
1 <?php
|
Chris@0
|
2
|
Chris@0
|
3 namespace Drupal\system;
|
Chris@0
|
4
|
Chris@0
|
5 use Drupal\Core\Controller\ControllerBase;
|
Chris@0
|
6 use Symfony\Component\HttpFoundation\Request;
|
Chris@0
|
7 use Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException;
|
Chris@0
|
8 use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
|
Chris@0
|
9 use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
Chris@0
|
10
|
Chris@0
|
11 /**
|
Chris@0
|
12 * System file controller.
|
Chris@0
|
13 */
|
Chris@0
|
14 class FileDownloadController extends ControllerBase {
|
Chris@0
|
15
|
Chris@0
|
16 /**
|
Chris@0
|
17 * Handles private file transfers.
|
Chris@0
|
18 *
|
Chris@0
|
19 * Call modules that implement hook_file_download() to find out if a file is
|
Chris@0
|
20 * accessible and what headers it should be transferred with. If one or more
|
Chris@0
|
21 * modules returned headers the download will start with the returned headers.
|
Chris@0
|
22 * If a module returns -1 an AccessDeniedHttpException will be thrown. If the
|
Chris@0
|
23 * file exists but no modules responded an AccessDeniedHttpException will be
|
Chris@0
|
24 * thrown. If the file does not exist a NotFoundHttpException will be thrown.
|
Chris@0
|
25 *
|
Chris@0
|
26 * @see hook_file_download()
|
Chris@0
|
27 *
|
Chris@0
|
28 * @param \Symfony\Component\HttpFoundation\Request $request
|
Chris@0
|
29 * The request object.
|
Chris@0
|
30 * @param string $scheme
|
Chris@0
|
31 * The file scheme, defaults to 'private'.
|
Chris@0
|
32 *
|
Chris@0
|
33 * @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
Chris@0
|
34 * The transferred file as response.
|
Chris@0
|
35 *
|
Chris@0
|
36 * @throws \Symfony\Component\HttpKernel\Exception\NotFoundHttpException
|
Chris@0
|
37 * Thrown when the requested file does not exist.
|
Chris@0
|
38 * @throws \Symfony\Component\HttpKernel\Exception\AccessDeniedHttpException
|
Chris@0
|
39 * Thrown when the user does not have access to the file.
|
Chris@0
|
40 */
|
Chris@0
|
41 public function download(Request $request, $scheme = 'private') {
|
Chris@0
|
42 $target = $request->query->get('file');
|
Chris@0
|
43 // Merge remaining path arguments into relative file path.
|
Chris@0
|
44 $uri = $scheme . '://' . $target;
|
Chris@0
|
45
|
Chris@0
|
46 if (file_stream_wrapper_valid_scheme($scheme) && file_exists($uri)) {
|
Chris@0
|
47 // Let other modules provide headers and controls access to the file.
|
Chris@0
|
48 $headers = $this->moduleHandler()->invokeAll('file_download', [$uri]);
|
Chris@0
|
49
|
Chris@0
|
50 foreach ($headers as $result) {
|
Chris@0
|
51 if ($result == -1) {
|
Chris@0
|
52 throw new AccessDeniedHttpException();
|
Chris@0
|
53 }
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 if (count($headers)) {
|
Chris@0
|
57 // \Drupal\Core\EventSubscriber\FinishResponseSubscriber::onRespond()
|
Chris@0
|
58 // sets response as not cacheable if the Cache-Control header is not
|
Chris@0
|
59 // already modified. We pass in FALSE for non-private schemes for the
|
Chris@0
|
60 // $public parameter to make sure we don't change the headers.
|
Chris@0
|
61 return new BinaryFileResponse($uri, 200, $headers, $scheme !== 'private');
|
Chris@0
|
62 }
|
Chris@0
|
63
|
Chris@0
|
64 throw new AccessDeniedHttpException();
|
Chris@0
|
65 }
|
Chris@0
|
66
|
Chris@0
|
67 throw new NotFoundHttpException();
|
Chris@0
|
68 }
|
Chris@0
|
69
|
Chris@0
|
70 }
|