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