| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-05-19 03:53:39 +08:00
										 |  |  | namespace BookStack\Http; | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | use Illuminate\Http\Request; | 
					
						
							|  |  |  | use Illuminate\Http\Response; | 
					
						
							|  |  |  | use Symfony\Component\HttpFoundation\StreamedResponse; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class DownloadResponseFactory | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2024-01-07 22:03:13 +08:00
										 |  |  |     public function __construct( | 
					
						
							|  |  |  |         protected Request $request | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create a response that directly forces a download in the browser. | 
					
						
							|  |  |  |      */ | 
					
						
							|  |  |  |     public function directly(string $content, string $fileName): Response | 
					
						
							|  |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-01-08 04:34:03 +08:00
										 |  |  |         return response()->make($content, 200, $this->getHeaders($fileName, strlen($content))); | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create a response that forces a download, from a given stream of content. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-01-07 22:03:13 +08:00
										 |  |  |     public function streamedDirectly($stream, string $fileName, int $fileSize): StreamedResponse | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-01-08 04:34:03 +08:00
										 |  |  |         $rangeStream = new RangeSupportedStream($stream, $fileSize, $this->request); | 
					
						
							|  |  |  |         $headers = array_merge($this->getHeaders($fileName, $fileSize), $rangeStream->getResponseHeaders()); | 
					
						
							|  |  |  |         return response()->stream( | 
					
						
							|  |  |  |             fn() => $rangeStream->outputAndClose(), | 
					
						
							|  |  |  |             $rangeStream->getResponseStatus(), | 
					
						
							|  |  |  |             $headers, | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Create a file download response that provides the file with a content-type | 
					
						
							|  |  |  |      * correct for the file, in a way so the browser can show the content in browser, | 
					
						
							|  |  |  |      * for a given content stream. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-01-07 22:03:13 +08:00
										 |  |  |     public function streamedInline($stream, string $fileName, int $fileSize): StreamedResponse | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2024-01-08 04:34:03 +08:00
										 |  |  |         $rangeStream = new RangeSupportedStream($stream, $fileSize, $this->request); | 
					
						
							| 
									
										
										
										
											2024-01-07 22:03:13 +08:00
										 |  |  |         $mime = $rangeStream->sniffMime(); | 
					
						
							| 
									
										
										
										
											2024-01-08 04:34:03 +08:00
										 |  |  |         $headers = array_merge($this->getHeaders($fileName, $fileSize, $mime), $rangeStream->getResponseHeaders()); | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-01-08 04:34:03 +08:00
										 |  |  |         return response()->stream( | 
					
						
							|  |  |  |             fn() => $rangeStream->outputAndClose(), | 
					
						
							|  |  |  |             $rangeStream->getResponseStatus(), | 
					
						
							|  |  |  |             $headers, | 
					
						
							|  |  |  |         ); | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Get the common headers to provide for a download response. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2024-01-08 04:34:03 +08:00
										 |  |  |     protected function getHeaders(string $fileName, int $fileSize, string $mime = 'application/octet-stream'): array | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |     { | 
					
						
							|  |  |  |         $disposition = ($mime === 'application/octet-stream') ? 'attachment' : 'inline'; | 
					
						
							|  |  |  |         $downloadName = str_replace('"', '', $fileName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return [ | 
					
						
							|  |  |  |             'Content-Type'           => $mime, | 
					
						
							| 
									
										
										
										
											2024-01-08 04:34:03 +08:00
										 |  |  |             'Content-Length'         => $fileSize, | 
					
						
							| 
									
										
										
										
											2022-06-09 06:50:42 +08:00
										 |  |  |             'Content-Disposition'    => "{$disposition}; filename=\"{$downloadName}\"", | 
					
						
							|  |  |  |             'X-Content-Type-Options' => 'nosniff', | 
					
						
							|  |  |  |         ]; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-06-10 19:37:14 +08:00
										 |  |  | } |