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