1: <?php
2:
3: 4: 5: 6:
7:
8: namespace Nette\Application\Responses;
9:
10: use Nette;
11:
12:
13: 14: 15: 16: 17: 18: 19:
20: class FileResponse extends Nette\Object implements Nette\Application\IResponse
21: {
22:
23: private $file;
24:
25:
26: private $contentType;
27:
28:
29: private $name;
30:
31:
32: public $resuming = TRUE;
33:
34:
35: private $forceDownload;
36:
37:
38: 39: 40: 41: 42:
43: public function __construct($file, $name = NULL, $contentType = NULL, $forceDownload = TRUE)
44: {
45: if (!is_file($file)) {
46: throw new Nette\Application\BadRequestException("File '$file' doesn't exist.");
47: }
48:
49: $this->file = $file;
50: $this->name = $name ? $name : basename($file);
51: $this->contentType = $contentType ? $contentType : 'application/octet-stream';
52: $this->forceDownload = $forceDownload;
53: }
54:
55:
56: 57: 58: 59:
60: public function getFile()
61: {
62: return $this->file;
63: }
64:
65:
66: 67: 68: 69:
70: public function getName()
71: {
72: return $this->name;
73: }
74:
75:
76: 77: 78: 79:
80: public function getContentType()
81: {
82: return $this->contentType;
83: }
84:
85:
86: 87: 88: 89:
90: public function send(Nette\Http\IRequest $httpRequest, Nette\Http\IResponse $httpResponse)
91: {
92: $httpResponse->setContentType($this->contentType);
93: $httpResponse->setHeader('Content-Disposition',
94: ($this->forceDownload ? 'attachment' : 'inline')
95: . '; filename="' . $this->name . '"'
96: . '; filename*=utf-8\'\'' . rawurlencode($this->name));
97:
98: $filesize = $length = filesize($this->file);
99: $handle = fopen($this->file, 'r');
100:
101: if ($this->resuming) {
102: $httpResponse->setHeader('Accept-Ranges', 'bytes');
103: if (preg_match('#^bytes=(\d*)-(\d*)\z#', $httpRequest->getHeader('Range'), $matches)) {
104: list(, $start, $end) = $matches;
105: if ($start === '') {
106: $start = max(0, $filesize - $end);
107: $end = $filesize - 1;
108:
109: } elseif ($end === '' || $end > $filesize - 1) {
110: $end = $filesize - 1;
111: }
112: if ($end < $start) {
113: $httpResponse->setCode(416);
114: return;
115: }
116:
117: $httpResponse->setCode(206);
118: $httpResponse->setHeader('Content-Range', 'bytes ' . $start . '-' . $end . '/' . $filesize);
119: $length = $end - $start + 1;
120: fseek($handle, $start);
121:
122: } else {
123: $httpResponse->setHeader('Content-Range', 'bytes 0-' . ($filesize - 1) . '/' . $filesize);
124: }
125: }
126:
127: $httpResponse->setHeader('Content-Length', $length);
128: while (!feof($handle) && $length > 0) {
129: echo $s = fread($handle, min(4e6, $length));
130: $length -= strlen($s);
131: }
132: fclose($handle);
133: }
134:
135: }
136: