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