77
88namespace Magento \Framework \App \Response ;
99
10+ use InvalidArgumentException ;
1011use Magento \Framework \App \Filesystem \DirectoryList ;
1112use Magento \Framework \App \Http \Context ;
13+ use Magento \Framework \App \PageCache \NotCacheableInterface ;
1214use Magento \Framework \App \Request \Http as HttpRequest ;
15+ use Magento \Framework \Exception \FileSystemException ;
1316use Magento \Framework \Filesystem ;
1417use Magento \Framework \Filesystem \Driver \File \Mime ;
1518use Magento \Framework \Session \Config \ConfigInterface ;
2023/**
2124 * @SuppressWarnings(PHPMD.CookieAndSessionMisuse)
2225 */
23- class File extends Http
26+ class File extends Http implements NotCacheableInterface
2427{
2528 /**
2629 * @var Http
@@ -63,6 +66,7 @@ class File extends Http
6366 * @param Mime $mime
6467 * @param array $fileOptions
6568 * @SuppressWarnings(PHPMD.ExcessiveParameterList)
69+ * @throws FileSystemException
6670 */
6771 public function __construct (
6872 HttpRequest $ request ,
@@ -81,45 +85,36 @@ public function __construct(
8185 $ this ->response = $ response ;
8286 $ this ->mime = $ mime ;
8387 $ this ->fileOptions = array_merge ($ this ->fileOptions , $ fileOptions );
88+ if (!isset ($ this ->fileOptions ['filePath ' ])) {
89+ throw new InvalidArgumentException ("File path is required " );
90+ }
91+ $ dir = $ this ->filesystem ->getDirectoryRead ($ this ->fileOptions ['directoryCode ' ]);
92+ if (!$ dir ->isExist ($ this ->fileOptions ['filePath ' ])) {
93+ throw new InvalidArgumentException ("File ' {$ this ->fileOptions ['filePath ' ]}' does not exists. " );
94+ }
95+ $ this ->setFileHeaders ();
8496 }
8597
8698 /**
8799 * @inheritDoc
88100 */
89101 public function sendResponse ()
90102 {
91- if ($ this ->fileOptions ['filePath ' ]) {
103+ $ this ->response ->sendHeaders ();
104+
105+ if (!$ this ->request ->isHead ()) {
92106 $ dir = $ this ->filesystem ->getDirectoryWrite ($ this ->fileOptions ['directoryCode ' ]);
93107 $ filePath = $ this ->fileOptions ['filePath ' ];
94- $ contentType = $ this ->fileOptions ['contentType ' ]
95- ?? $ dir ->stat ($ filePath )['mimeType ' ]
96- ?? $ this ->mime ->getMimeType ($ dir ->getAbsolutePath ($ filePath ));
97- $ contentLength = $ this ->fileOptions ['contentLength ' ]
98- ?? $ dir ->stat ($ filePath )['size ' ];
99- $ fileName = $ this ->fileOptions ['fileName ' ]
100- ?? basename ($ filePath );
101- $ this ->response ->setHttpResponseCode (200 );
102- $ this ->response ->setHeader ('Content-type ' , $ contentType , true )
103- ->setHeader ('Content-Length ' , $ contentLength )
104- ->setHeader ('Content-Disposition ' , 'attachment; filename=" ' . $ fileName . '" ' , true )
105- ->setHeader ('Pragma ' , 'public ' , true )
106- ->setHeader ('Cache-Control ' , 'must-revalidate, post-check=0, pre-check=0 ' , true )
107- ->setHeader ('Last-Modified ' , date ('r ' ), true );
108-
109- $ this ->response ->sendHeaders ();
110-
111- if (!$ this ->request ->isHead ()) {
112- $ stream = $ dir ->openFile ($ filePath , 'r ' );
113- while (!$ stream ->eof ()) {
114- // phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
115- echo $ stream ->read (1024 );
116- }
117- $ stream ->close ();
118- if ($ this ->fileOptions ['remove ' ]) {
119- $ dir ->delete ($ filePath );
120- }
121- $ this ->response ->clearBody ();
108+ $ stream = $ dir ->openFile ($ filePath , 'r ' );
109+ while (!$ stream ->eof ()) {
110+ // phpcs:ignore Magento2.Security.LanguageConstruct.DirectOutput
111+ echo $ stream ->read (1024 );
112+ }
113+ $ stream ->close ();
114+ if ($ this ->fileOptions ['remove ' ]) {
115+ $ dir ->delete ($ filePath );
122116 }
117+ $ this ->response ->clearBody ();
123118 }
124119 return $ this ;
125120 }
@@ -148,4 +143,30 @@ public function clearHeader($name)
148143 {
149144 return $ this ->response ->clearHeader ($ name );
150145 }
146+
147+ /**
148+ * Set appropriate headers for the file attachment
149+ *
150+ * @return void
151+ * @throws \Magento\Framework\Exception\FileSystemException
152+ */
153+ private function setFileHeaders (): void
154+ {
155+ $ dir = $ this ->filesystem ->getDirectoryWrite ($ this ->fileOptions ['directoryCode ' ]);
156+ $ filePath = $ this ->fileOptions ['filePath ' ];
157+ $ contentType = $ this ->fileOptions ['contentType ' ]
158+ ?? $ dir ->stat ($ filePath )['mimeType ' ]
159+ ?? $ this ->mime ->getMimeType ($ dir ->getAbsolutePath ($ filePath ));
160+ $ contentLength = $ this ->fileOptions ['contentLength ' ]
161+ ?? $ dir ->stat ($ filePath )['size ' ];
162+ $ fileName = $ this ->fileOptions ['fileName ' ]
163+ ?? basename ($ filePath );
164+ $ this ->response ->setHttpResponseCode (200 );
165+ $ this ->response ->setHeader ('Content-type ' , $ contentType , true )
166+ ->setHeader ('Content-Length ' , $ contentLength )
167+ ->setHeader ('Content-Disposition ' , 'attachment; filename=" ' . $ fileName . '" ' , true )
168+ ->setHeader ('Pragma ' , 'public ' , true )
169+ ->setHeader ('Cache-Control ' , 'must-revalidate, post-check=0, pre-check=0 ' , true )
170+ ->setHeader ('Last-Modified ' , date ('r ' ), true );
171+ }
151172}
0 commit comments