@@ -19,6 +19,17 @@ class File
1919 */
2020 public $ delete = true ;
2121
22+ /**
23+ * @var array the list of static default headers to send when `send()` is
24+ * called as key/value pairs.
25+ */
26+ public static $ defaultHeaders = array (
27+ 'Pragma ' => 'public ' ,
28+ 'Expires ' => 0 ,
29+ 'Cache-Control ' => 'must-revalidate, post-check=0, pre-check=0 ' ,
30+ 'Content-Transfer-Encoding ' => 'binary ' ,
31+ );
32+
2233 /**
2334 * @var string the name of this file
2435 */
@@ -73,40 +84,48 @@ public function __destruct()
7384 * 'application/octet-stream' is used.
7485 * @param bool $inline whether to force inline display of the file, even if
7586 * filename is present.
87+ * @param array $headers a list of additional HTTP headers to send in the
88+ * response as an array. The array keys are the header names like
89+ * 'Cache-Control' and the array values the header value strings to send.
90+ * Each array value can also be another array of strings if the same header
91+ * should be sent multiple times. This can also be used to override
92+ * automatically created headers like 'Expires' or 'Content-Length'. To suppress
93+ * automatically created headers, `false` can also be used as header value.
7694 */
77- public function send ($ filename = null , $ contentType = null , $ inline = false )
95+ public function send ($ filename = null , $ contentType = null , $ inline = false , $ headers = array () )
7896 {
79- if ($ contentType === null ) {
97+ $ headers = array_merge (self ::$ defaultHeaders , $ headers );
98+
99+ if ($ contentType !== null ) {
100+ $ headers ['Content-Type ' ] = $ contentType ;
101+ } elseif (!isset ($ headers ['Content-Type ' ])) {
80102 $ contentType = @mime_content_type ($ this ->_filename );
81103 if ($ contentType === false ) {
82104 $ contentType = self ::DEFAULT_CONTENT_TYPE ;
83105 }
106+ $ headers ['Content-Type ' ] = $ contentType ;
84107 }
85- header ('Pragma: public ' );
86- header ('Expires: 0 ' );
87- header ('Cache-Control: must-revalidate, post-check=0, pre-check=0 ' );
88- header ('Content-Type: ' . $ contentType );
89- header ('Content-Transfer-Encoding: binary ' );
90-
91- //#11 Undefined index: HTTP_USER_AGENT
92- $ userAgent = isset ($ _SERVER ['HTTP_USER_AGENT ' ]) ? $ _SERVER ['HTTP_USER_AGENT ' ] : '' ;
93-
94- // #84: Content-Length leads to "network connection was lost" on iOS
95- $ isIOS = preg_match ('/i(phone|pad|pod)/i ' , $ userAgent );
96- if (!$ isIOS ) {
97- header ('Content-Length: ' . filesize ($ this ->_fileName ));
108+
109+ if (!isset ($ headers ['Content-Length ' ])) {
110+ // #11 Undefined index: HTTP_USER_AGENT
111+ $ userAgent = isset ($ _SERVER ['HTTP_USER_AGENT ' ]) ? $ _SERVER ['HTTP_USER_AGENT ' ] : '' ;
112+
113+ // #84: Content-Length leads to "network connection was lost" on iOS
114+ $ isIOS = preg_match ('/i(phone|pad|pod)/i ' , $ userAgent );
115+ if (!$ isIOS ) {
116+ $ headers ['Content-Length ' ] = filesize ($ this ->_fileName );
117+ }
98118 }
99119
100- if ($ filename !== null || $ inline ) {
120+ if (( $ filename !== null || $ inline) && ! isset ( $ headers [ ' Content-Disposition ' ]) ) {
101121 $ disposition = $ inline ? 'inline ' : 'attachment ' ;
102122 $ encodedFilename = rawurlencode ($ filename );
103- header (
104- "Content-Disposition: $ disposition; " .
123+ $ headers ['Content-Disposition ' ] = "$ disposition; " .
105124 "filename= \"$ filename \"; " .
106- "filename*=UTF-8'' $ encodedFilename "
107- );
125+ "filename*=UTF-8'' $ encodedFilename " ;
108126 }
109127
128+ $ this ->sendHeaders ($ headers );
110129 readfile ($ this ->_fileName );
111130 }
112131
@@ -152,4 +171,27 @@ public function __toString()
152171 {
153172 return $ this ->_fileName ;
154173 }
174+
175+ /**
176+ * Send the given list of headers
177+ *
178+ * @param array $headers the list of headers to send as key/value pairs.
179+ * Value can either be a string or an array of strings to send the same
180+ * header multiple times.
181+ */
182+ protected function sendHeaders ($ headers )
183+ {
184+ foreach ($ headers as $ name => $ value ) {
185+ if ($ value === false ) {
186+ continue ;
187+ }
188+ if (is_array ($ value )) {
189+ foreach ($ value as $ v ) {
190+ header ("$ name: $ v " );
191+ }
192+ } else {
193+ header ("$ name: $ value " );
194+ }
195+ }
196+ }
155197}
0 commit comments