Skip to content

Commit eb5bc06

Browse files
committed
Added workign with uploaded files docs
1 parent dd7b5f5 commit eb5bc06

3 files changed

Lines changed: 207 additions & 11 deletions

File tree

system/HTTP/Files/UploadedFile.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,10 @@ public function move(string $targetPath, string $name = null): bool
170170
throw new \RuntimeException('The original file is not a valid file.');
171171
}
172172

173-
if (! @move_uploaded_file($this->path, $targetPath))
173+
$targetPath = rtrim($targetPath, '/').'/';
174+
$name = is_null($name) ? $this->getName() : $name;
175+
176+
if (! @move_uploaded_file($this->path, $targetPath.$name))
174177
{
175178
$error = error_get_last();
176179
throw new \RuntimeException(sprintf('Could not move file %s to %s (%s)', basename($this->path), $targetPath, strip_tags($error['message'])));
@@ -224,7 +227,7 @@ public function getSize(string $unit='b'): int
224227
$this->size = filesize($this->path);
225228
}
226229

227-
switch ($unit)
230+
switch (strtolower($unit))
228231
{
229232
case 'kb':
230233
return number_format($this->size / 1024, 3);
@@ -328,7 +331,7 @@ public function getTempName(): string
328331
*/
329332
public function getRandomName(): string
330333
{
331-
return time().'_'.random_bytes(8).'.'.$this->$this->getExtension();
334+
return time().'_'.random_bytes(10).'.'.$this->$this->getExtension();
332335
}
333336

334337
//--------------------------------------------------------------------

system/HTTP/IncomingRequest.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ public function getFiles(): array
324324
{
325325
if (is_null($this->files))
326326
{
327-
// @todo modify to use the Services, at the very least.
327+
// @todo modify to use Services, at the very least.
328328
$this->files = new FileCollection();
329329
}
330330

@@ -345,15 +345,10 @@ public function getFile(string $fileID)
345345
{
346346
if (is_null($this->files))
347347
{
348-
// @todo modify to use the Services, at the very least.
348+
// @todo modify to use Services, at the very least.
349349
$this->files = new FileCollection();
350350
}
351351

352-
if ( ! $this->files->hasFile($fileID))
353-
{
354-
return null;
355-
}
356-
357352
return $this->files->getFile($fileID);
358353
}
359354

user_guide_src/source/libraries/uploaded_files.rst

Lines changed: 199 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,202 @@
22
Working with Uploaded Files
33
***************************
44

5-
TODO
5+
CodeIgniter makes working with files uploaded through a form much simpler and more secure than using PHP's ``$_FILES``
6+
array directly.
7+
8+
.. note:: This is not the same as the File Uploading class in previous versions of CodeIgniter. This provides a raw
9+
interface to the uploaded files with a few small features. An uploader class will be present in the final release.
10+
11+
.. contents::
12+
:local:
13+
14+
===============
15+
Accessing Files
16+
===============
17+
18+
When you upload files they can be accessed natively in PHP through the ``$_FILES`` superglobal. This array has some
19+
major shortcomings when working with multiple files uploaded at once, and has potential security flaws many developers
20+
are not aware of. CodeIgniter helps with both of these situations by standardizing your usage of files behind a
21+
common interface.
22+
23+
Files are accessed through the current ``IncomingRequest`` instance. To retrieve all files that were uploaded with this
24+
request, use ``getFiles()``. This will return an array of files represented by instances of ``CodeIgniter\HTTP\Files\UploadedFile``.
25+
::
26+
27+
$files = $this->request->getFiles();
28+
29+
Of course, there are multiple ways to name the file input, and anything but the simplest can create strange results.
30+
The array returns in a manner that you would expect. With the simplest usage, a single file might be submitted like::
31+
32+
<input type="file" name="avatar" />
33+
34+
Which would return a simple array like::
35+
36+
[
37+
'avatar' => // UploadedFile instance
38+
]
39+
40+
If you used an array notation for the name, the input would look something like::
41+
42+
<input type="file" name="my-form[details][avatar]" />
43+
44+
The array returned by ``getFiles()`` would look more like this::
45+
46+
[
47+
'my-form' => [
48+
'details' => [
49+
'avatar' => // UploadedFile instance
50+
]
51+
]
52+
]
53+
54+
In some cases, you may specify an array of files to upload::
55+
56+
Upload an avatar: <input type="file" name="my-form[details][avatars][]" />
57+
Upload an avatar: <input type="file" name="my-form[details][avatars][]" />
58+
59+
In this case, the returned array of files would be more like::
60+
61+
[
62+
'my-form' => [
63+
'details' => [
64+
'avatar' => [
65+
0 => /* UploadedFile instance */,
66+
1 => /* UploadedFile instance */
67+
]
68+
]
69+
]
70+
71+
If you just need to access a single file, you can use ``getFile()`` to retrieve the file instance directly::
72+
73+
$file = $this->request->getFile('avatar');
74+
75+
.. note:: This currently only works with simple file names and not with array syntax naming.
76+
77+
=====================
78+
Working With the File
79+
=====================
80+
81+
Once you've gotten the UploadedFile instance, you can retrieve information about the file in safe ways, as well as
82+
move the file to a new location.
83+
84+
Verify A File
85+
-------------
86+
87+
You can check that a file was actually uploaded via HTTP with no errors by calling the ``isValid()`` method::
88+
89+
if (! $file->isValid())
90+
{
91+
throw new RuntimeException($file->getErrorString().'('.$file->getError().')');
92+
}
93+
94+
As seen in this example, if a file had an upload error, you can retrieve the error code (an integer) and the error
95+
message with the ``getError()`` and ``getErrorString()`` methods. The following errors can be discovered through
96+
this method:
97+
98+
* The file exceeds your upload_max_filesize ini directive.
99+
* The file exceeds the upload limit defined in your form.
100+
* The file was only partially uploaded.
101+
* No file was uploaded.
102+
* The file could not be written on disk.
103+
* File could not be uploaded: missing temporary directory.
104+
* File upload was stopped by a PHP extension.
105+
106+
File Names
107+
----------
108+
109+
**getName()**
110+
111+
You can retrieve the original filename provided by the client with the ``getName()`` method. This will typically be the
112+
filename sent by the client, and should not be trusted. If the file has been moved, this will return the final name of
113+
the moved file.::
114+
115+
$name = $file->getName();
116+
117+
**getTempName()**
118+
119+
To get the name of the temp file that was created during the upload, you can use the ``getTempName()`` method.::
120+
121+
$tempfile = $file->getTempName();
122+
123+
**getRandomName()**
124+
125+
You can generate a cryptographically secure random filename, with the current timestamp prepended, with the ``getRandomName()``
126+
method. This is especially useful to rename files when moving it so that the filename is unguessable.
127+
::
128+
129+
// Generates something like: 1465965676_385e33f741.jpg
130+
$newName = $file->getRandomName();
131+
132+
133+
Other File Info
134+
---------------
135+
136+
**getExtension()**
137+
138+
Attempts to determine the file extension based on the trusted ``getType()`` method instead of the value listed
139+
in ``$_FILES``. If the mime type is unknown, will return null. Uses the values in **application/Config/Mimes.php**
140+
to determine extension.
141+
::
142+
143+
// Returns 'jpg' (WITHOUT the period)
144+
$ext = $file->getExtension();
145+
146+
**getClientExtension()**
147+
148+
Returns the original file extension, based on the file name that was uploaded. This is NOT a trusted source. For a
149+
trusted version, use ``getExtension()`` instead.
150+
::
151+
152+
$ext = $file->getClientExtension();
153+
154+
**getType()**
155+
156+
Retrieve the media type (mime type) of the file. Does not use information from the $_FILES array, but uses other methods to more
157+
accurately determine the type of file, like ``finfo``, or ``mime_content_type``.
158+
::
159+
160+
$type = $file->getType();
161+
162+
echo $type; // image/png
163+
164+
**getClientType()**
165+
166+
Returns the mime type (mime type) of the file as provided by the client. This is NOT a trusted value. For a trusted
167+
version, use ``getType()`` instead.
168+
::
169+
170+
$type = $file->getClientType();
171+
172+
echo $type; // image/png
173+
174+
**getSize()**
175+
176+
Returns the size of the uploaded file in bytes. You can pass in either 'kb' or 'mb' as the first parameter to get
177+
the results in kilobytes or megabytes, respectively.
178+
::
179+
180+
$bytes = $file->getSize(); // 256901
181+
$kilobytes = $file->getSize('kb'); // 250.880
182+
$megabytes = $file->getSize('mb'); // 0.245
183+
184+
Moving Files
185+
------------
186+
187+
Each file can be moved to its new location with the aptly named ``move()`` method. This takes the directory to move
188+
the file to as the first parameter::
189+
190+
$file->move(WRITEPATH.'uploads');
191+
192+
By default, the original filename was used. You can specify a new filename by passing it as the second parameter::
193+
194+
$newName = $file->getRandomName();
195+
$file->move(WRITEPATH.'uploads', $newName);
196+
197+
Once the file has been removed the temporary file is deleted. You can check if a file has been moved already with
198+
the ``hasMoved()`` method, which returns a boolean::
199+
200+
if ($file->isValid() && ! $file->hasMoved())
201+
{
202+
$file->move($path);
203+
}

0 commit comments

Comments
 (0)