]> BookStack Code Mirror - bookstack/blob - app/Http/DownloadResponseFactory.php
Lexical: Updated tests for node changes
[bookstack] / app / Http / DownloadResponseFactory.php
1 <?php
2
3 namespace BookStack\Http;
4
5 use Illuminate\Http\Request;
6 use Illuminate\Http\Response;
7 use Symfony\Component\HttpFoundation\StreamedResponse;
8
9 class DownloadResponseFactory
10 {
11     public function __construct(
12         protected Request $request
13     ) {
14     }
15
16     /**
17      * Create a response that directly forces a download in the browser.
18      */
19     public function directly(string $content, string $fileName): Response
20     {
21         return response()->make($content, 200, $this->getHeaders($fileName, strlen($content)));
22     }
23
24     /**
25      * Create a response that forces a download, from a given stream of content.
26      */
27     public function streamedDirectly($stream, string $fileName, int $fileSize): StreamedResponse
28     {
29         $rangeStream = new RangeSupportedStream($stream, $fileSize, $this->request);
30         $headers = array_merge($this->getHeaders($fileName, $fileSize), $rangeStream->getResponseHeaders());
31         return response()->stream(
32             fn() => $rangeStream->outputAndClose(),
33             $rangeStream->getResponseStatus(),
34             $headers,
35         );
36     }
37
38     /**
39      * Create a file download response that provides the file with a content-type
40      * correct for the file, in a way so the browser can show the content in browser,
41      * for a given content stream.
42      */
43     public function streamedInline($stream, string $fileName, int $fileSize): StreamedResponse
44     {
45         $rangeStream = new RangeSupportedStream($stream, $fileSize, $this->request);
46         $mime = $rangeStream->sniffMime();
47         $headers = array_merge($this->getHeaders($fileName, $fileSize, $mime), $rangeStream->getResponseHeaders());
48
49         return response()->stream(
50             fn() => $rangeStream->outputAndClose(),
51             $rangeStream->getResponseStatus(),
52             $headers,
53         );
54     }
55
56     /**
57      * Get the common headers to provide for a download response.
58      */
59     protected function getHeaders(string $fileName, int $fileSize, string $mime = 'application/octet-stream'): array
60     {
61         $disposition = ($mime === 'application/octet-stream') ? 'attachment' : 'inline';
62         $downloadName = str_replace('"', '', $fileName);
63
64         return [
65             'Content-Type'           => $mime,
66             'Content-Length'         => $fileSize,
67             'Content-Disposition'    => "{$disposition}; filename=\"{$downloadName}\"",
68             'X-Content-Type-Options' => 'nosniff',
69         ];
70     }
71 }