@@ -19,6 +19,17 @@ class File
19
19
*/
20
20
public $ delete = true ;
21
21
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
+
22
33
/**
23
34
* @var string the name of this file
24
35
*/
@@ -73,40 +84,48 @@ public function __destruct()
73
84
* 'application/octet-stream' is used.
74
85
* @param bool $inline whether to force inline display of the file, even if
75
86
* 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.
76
94
*/
77
- public function send ($ filename = null , $ contentType = null , $ inline = false )
95
+ public function send ($ filename = null , $ contentType = null , $ inline = false , $ headers = array () )
78
96
{
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 ' ])) {
80
102
$ contentType = @mime_content_type ($ this ->_filename );
81
103
if ($ contentType === false ) {
82
104
$ contentType = self ::DEFAULT_CONTENT_TYPE ;
83
105
}
106
+ $ headers ['Content-Type ' ] = $ contentType ;
84
107
}
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
+ }
98
118
}
99
119
100
- if ($ filename !== null || $ inline ) {
120
+ if (( $ filename !== null || $ inline) && ! isset ( $ headers [ ' Content-Disposition ' ]) ) {
101
121
$ disposition = $ inline ? 'inline ' : 'attachment ' ;
102
122
$ encodedFilename = rawurlencode ($ filename );
103
- header (
104
- "Content-Disposition: $ disposition; " .
123
+ $ headers ['Content-Disposition ' ] = "$ disposition; " .
105
124
"filename= \"$ filename \"; " .
106
- "filename*=UTF-8'' $ encodedFilename "
107
- );
125
+ "filename*=UTF-8'' $ encodedFilename " ;
108
126
}
109
127
128
+ $ this ->sendHeaders ($ headers );
110
129
readfile ($ this ->_fileName );
111
130
}
112
131
@@ -152,4 +171,27 @@ public function __toString()
152
171
{
153
172
return $ this ->_fileName ;
154
173
}
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
+ }
155
197
}
0 commit comments