@@ -34,6 +34,7 @@ class BinaryFileResponse extends Response
3434 protected $ offset = 0 ;
3535 protected $ maxlen = -1 ;
3636 protected $ deleteFileAfterSend = false ;
37+ protected $ chunkSize = 8 * 1024 ;
3738
3839 /**
3940 * @param \SplFileInfo|string $file The file to stream
@@ -124,6 +125,22 @@ public function getFile()
124125 return $ this ->file ;
125126 }
126127
128+ /**
129+ * Sets the response stream chunk size.
130+ *
131+ * @return $this
132+ */
133+ public function setChunkSize (int $ chunkSize ): self
134+ {
135+ if ($ chunkSize < 1 || $ chunkSize > \PHP_INT_MAX ) {
136+ throw new \LogicException ('The chunk size of a BinaryFileResponse cannot be less than 1 or greater than PHP_INT_MAX. ' );
137+ }
138+
139+ $ this ->chunkSize = $ chunkSize ;
140+
141+ return $ this ;
142+ }
143+
127144 /**
128145 * Automatically sets the Last-Modified header according the file modification date.
129146 */
@@ -303,7 +320,23 @@ public function sendContent()
303320 $ out = fopen ('php://output ' , 'w ' );
304321 $ file = fopen ($ this ->file ->getPathname (), 'r ' );
305322
306- stream_copy_to_stream ($ file , $ out , $ this ->maxlen , $ this ->offset );
323+ ignore_user_abort (true );
324+
325+ if (0 !== $ this ->offset ) {
326+ fseek ($ file , $ this ->offset );
327+ }
328+
329+ $ length = $ this ->maxlen ;
330+ while ($ length && !feof ($ file )) {
331+ $ read = ($ length > $ this ->chunkSize ) ? $ this ->chunkSize : $ length ;
332+ $ length -= $ read ;
333+
334+ stream_copy_to_stream ($ file , $ out , $ read );
335+
336+ if (connection_aborted ()) {
337+ break ;
338+ }
339+ }
307340
308341 fclose ($ out );
309342 fclose ($ file );
0 commit comments