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