1: <?php
2:
3: /**
4: * This file is part of the Nette Framework (https://nette.org)
5: * Copyright (c) 2004 David Grudl (http://davidgrudl.com)
6: */
7:
8: namespace Nette\Http;
9:
10: use Nette;
11:
12:
13: /**
14: * Provides access to individual files that have been uploaded by a client.
15: *
16: * @author David Grudl
17: *
18: * @property-read string $name
19: * @property-read string $sanitizedName
20: * @property-read string $contentType
21: * @property-read int $size
22: * @property-read string $temporaryFile
23: * @property-read int $error
24: * @property-read bool $ok
25: * @property-read bool $image
26: * @property-read array $imageSize
27: * @property-read string $contents
28: */
29: class FileUpload extends Nette\Object
30: {
31: /** @var string */
32: private $name;
33:
34: /** @var string */
35: private $type;
36:
37: /** @var string */
38: private $size;
39:
40: /** @var string */
41: private $tmpName;
42:
43: /** @var int */
44: private $error;
45:
46:
47: public function __construct($value)
48: {
49: foreach (array('name', 'type', 'size', 'tmp_name', 'error') as $key) {
50: if (!isset($value[$key]) || !is_scalar($value[$key])) {
51: $this->error = UPLOAD_ERR_NO_FILE;
52: return; // or throw exception?
53: }
54: }
55: $this->name = $value['name'];
56: $this->size = $value['size'];
57: $this->tmpName = $value['tmp_name'];
58: $this->error = $value['error'];
59: }
60:
61:
62: /**
63: * Returns the file name.
64: * @return string
65: */
66: public function getName()
67: {
68: return $this->name;
69: }
70:
71:
72: /**
73: * Returns the sanitized file name.
74: * @return string
75: */
76: public function getSanitizedName()
77: {
78: return trim(Nette\Utils\Strings::webalize($this->name, '.', FALSE), '.-');
79: }
80:
81:
82: /**
83: * Returns the MIME content type of an uploaded file.
84: * @return string
85: */
86: public function getContentType()
87: {
88: if ($this->isOk() && $this->type === NULL) {
89: $this->type = Nette\Utils\MimeTypeDetector::fromFile($this->tmpName);
90: }
91: return $this->type;
92: }
93:
94:
95: /**
96: * Returns the size of an uploaded file.
97: * @return int
98: */
99: public function getSize()
100: {
101: return $this->size;
102: }
103:
104:
105: /**
106: * Returns the path to an uploaded file.
107: * @return string
108: */
109: public function getTemporaryFile()
110: {
111: return $this->tmpName;
112: }
113:
114:
115: /**
116: * Returns the path to an uploaded file.
117: * @return string
118: */
119: public function __toString()
120: {
121: return (string) $this->tmpName;
122: }
123:
124:
125: /**
126: * Returns the error code. {@link http://php.net/manual/en/features.file-upload.errors.php}
127: * @return int
128: */
129: public function getError()
130: {
131: return $this->error;
132: }
133:
134:
135: /**
136: * Is there any error?
137: * @return bool
138: */
139: public function isOk()
140: {
141: return $this->error === UPLOAD_ERR_OK;
142: }
143:
144:
145: /**
146: * Move uploaded file to new location.
147: * @param string
148: * @return self
149: */
150: public function move($dest)
151: {
152: @mkdir(dirname($dest), 0777, TRUE); // @ - dir may already exist
153: @unlink($dest); // @ - file may not exists
154: if (!call_user_func(is_uploaded_file($this->tmpName) ? 'move_uploaded_file' : 'rename', $this->tmpName, $dest)) {
155: throw new Nette\InvalidStateException("Unable to move uploaded file '$this->tmpName' to '$dest'.");
156: }
157: chmod($dest, 0666);
158: $this->tmpName = $dest;
159: return $this;
160: }
161:
162:
163: /**
164: * Is uploaded file GIF, PNG or JPEG?
165: * @return bool
166: */
167: public function isImage()
168: {
169: return in_array($this->getContentType(), array('image/gif', 'image/png', 'image/jpeg'), TRUE);
170: }
171:
172:
173: /**
174: * Returns the image.
175: * @return Nette\Image
176: */
177: public function toImage()
178: {
179: return Nette\Image::fromFile($this->tmpName);
180: }
181:
182:
183: /**
184: * Returns the dimensions of an uploaded image as array.
185: * @return array
186: */
187: public function getImageSize()
188: {
189: return $this->isOk() ? @getimagesize($this->tmpName) : NULL; // @ - files smaller than 12 bytes causes read error
190: }
191:
192:
193: /**
194: * Get file contents.
195: * @return string
196: */
197: public function getContents()
198: {
199: // future implementation can try to work around safe_mode and open_basedir limitations
200: return $this->isOk() ? file_get_contents($this->tmpName) : NULL;
201: }
202:
203: }
204: