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