Sunday, March 1, 2009

Uploading Files in PHP

When working with the Uploading Files in PHP we need to consider the following things:

1.Understanding how PHP handles file uploads
2.Restricting the size and type of uploads
3.Preventing files from being overwritten
4.Organizing uploads into specific folders
5.Handling multiple uploads

The way that PHP handles file uploads makes it relatively simple to restrict the
type and size of files accepted. What it cannot do is check the suitability of the content. It’s therefore always a good idea to implement a strategy that prevents indecent or illegal material from being automatically displayed on your site. One way is to store uploaded material in a nonpublic directory until it has been approved. Another way is to restrict uploads to registered and trusted users by placing the upload form in a password protected area. A combination of both approaches is even more secure.

How PHP handles file uploads
The term “upload” means moving a file from one computer to another, but as far as PHP
is concerned, all that’s happening is that a file is being moved from one location to
another. This means you can test all the scripts in this chapter on your local computer
without the need to upload files to a remote server.

PHP supports file uploads by default, but hosting companies can restrict the size of
uploads or disable them altogether. Before going any further, it’s a good idea to check the
settings on your remote server.

The first and most important thing to check before file upload is "Checking whether your server supports uploads"

You can check by the following command. Type this is your editor and save it as .PHP and run it. Now you must satisfy the below conditions.

Directive
Default value
Description

The definition for the below description

max_execution_time -- Directive
30 -- Default value
The maximum number of seconds that a PHP script can run. If the script takes longer, PHP generates a fatal error.

max_input_time
60
The maximum number of seconds that a PHP script is allowed to parse the $_POST and $_GET arrays, and file uploads. Very large uploads are likely to run out of time.

post_max_size
8M
The maximum permitted size of all $_POST data, including file uploads.Although the default is 8MB, hosting companies may impose a smaller limit.

upload_tmp_dir
This is where PHP stores uploaded files until your script moves them toa permanent location. If no value is defined in php.ini, PHP uses the system default temporary directory.

upload_max_filesize
2M
The maximum permitted size of a single upload file. Although the default is 2MB,
hosting companies may impose a smaller limit. A number on its own indicates the
number of bytes permitted. A number followed by K indicates the number of kilobytes permitted.

It’s important to note the limit imposed by post_max_size. Even though the default
values theoretically permit the simultaneous upload of four 2MB files, the upload is likely to fail because the content of the $_POST array would bring the total to more than 8MB.

If the Local Value of file_uploads is Off, uploads have been disabled. There is nothing you
can do about it, other than ask your hosting company if it offers a package with file
uploading enabled. Your only alternatives are to move to a different host or to use a different solution, such as uploading files by FTP.

Simple for with File upload option

<form action="" method="post" enctype="multipart/form-data"
name="uploadImage" id="uploadImage">
<p>
<label for="image">Upload image:</label>
<input type="file" name="image" id="image" />
</p>
<p>
<input type="submit" name="upload" id="upload" value="Upload" />
</p>
</form>

The PHP code for Uploading files is:

<?php
if (array_key_exists('upload', $_POST)) {
// define constant for upload folder
define('UPLOAD_DIR', 'path/to/upload_test/');
// move the file to the upload folder and rename it
move_uploaded_file($_FILES['image']['tmp_name'],
UPLOAD_DIR.$_FILES['image']['name']);
}
?>

Inspecting the $_FILES array

In above code before writing the Uploading code just add below code to under what the $_FILES array contains:

<pre>
<?php
if (array_key_exists('upload', $_POST)) {
print_r($_FILES);
}
?>
</pre>
</body>

checks whether the $_POST array contains upload, the name attribute of the submit
button. If it does, you know the form has been submitted, so you can use
print_r() to inspect the $_FILES array. The <pre> tags make the output easier
to read.

O/P is:

Array {
[image] => Array
{
[name] = testimage.jpg
[type] = image/jpeg
[tmp_name] = c:\window\temp\phpt3.tmp
[error] = 0
[size] = 9603
}
}

You can see that the $_FILES array is actually a multidimensional array. The key (or
name) of the top-level array comes from the name attribute of the file input field—
in this case, image. The image subarray consists of five elements, namely

name: The original name of the uploaded file
type: The uploaded file’s MIME type
tmp_name: The location of the uploaded file
error: An integer indicating any problems with the upload
size: The size of the uploaded file in bytes


Meaning of the different error levels in the $_FILES array


Error level Meaning
0 Upload successful
1 File exceeds maximum upload size specified in php.ini (default 2MB)
2 File exceeds size specified by MAX_FILE_SIZE embedded in the form
3 File only partially uploaded
4 Form submitted with no file specified
5 Currently not defined
6 No temporary folder (PHP 4.3.10 and 5.0.3 and above)
7 Cannot write file to disk (PHP 5.1.0 and above)

Another important error/warning message is:

Another frequent source of confusion is the question of file ownership and how PHP runs on a web server. If you’re testing in Windows, an upload script that has been working perfectly may confront you with a message like this when you transfer it to your remote server:

Warning: move_uploaded_file(/home/user/htdocs/testarea/kinkakuji.jpg)
[function.move-uploaded-file]: failed to open stream: Permission
denied in /home/user/htdocs/testarea/upload_test.php on line 3

Since 777 is the least secure setting, you need to adopt a cautious approach to file
uploads. Begin by testing upload scripts with a setting of 700. If that doesn’t work, try 770, and use 777 only as a last resort. Your upload directory doesn’t need to be within your site root; it can be anywhere on the server. If your hosting company gives you a private directory outside the site root, the most secure solution is to create a subdirectory for uploads inside the private one. Alternatively, create a directory inside your site root, but don’t link to it from any web pages. Give it an innocuous name, such as lastyear

here you can define the folder path where you can upload the files by Define function:

define('UPLOAD_DIR', 'C:/upload_test/');

Note:

If a file of the same name already exists in the upload folder, the new file will
overwrite it without warning.

You may come across scripts that use copy() instead of move_uploaded_file().
Without other checks in place, copy() can expose your website to serious security
risks. Always use move_uploaded_file(); it’s much more secure.

Removing spaces from filenames

Windows and Mac OS X allow you to create long filenames with spaces in them. It makes
them easier to recognize, but spaces in filenames can wreak havoc on Linux servers. Even if your remote server runs on Windows, you should remove all spaces in the names of files likely to be used in web pages, and replace them with hyphens or underscores. This is easily done with a function called str_replace(), which searches for all occurrences of a string within a string, and replaces them with another. The search string can consist of one or more characters, and the replacement string can be zero or more characters. (Using zero characters in the replacement string—a pair of quotes with nothing between them — effectively removes the search string from the target string.) Although you may not think of a space as being a string, it’s just the same as any other character to PHP.

define('UPLOAD_DIR', 'C:/upload_test/');
// replace any spaces in original filename with underscores
// at the same time, assign to a simpler variable
$file = str_replace(' ', '_', $_FILES['image']['name']);

The function str_replace() takes the following three arguments:

The character or substring that you want to replace—in this case, a space
The character or substring that you want to insert—in this case, an underscore
The string that you want to update—in this case, $_FILES['image']['name']

You’ll need to make frequent references to the filename later, so it’s a good idea to
assign the updated filename to a simpler variable, $file, at the same time.

You can make use of the shorter variable right away by amending the line that
moves the uploaded file as follows:

Rejecting large files

The ability to upload files is not enough on its own: you need to make your form more
secure. The first step is to set a maximum size for file uploads. Even if your hosting company sets a lower limit than the 2MB default, you may want to set a much lower limit yourself. At the same time, it’s a good idea to make your form more user-friendly by reporting whether the upload was successful. You can do this easily by checking the error level reported by the $_FILES array

move_uploaded_file($_FILES['image']['tmp_name'], UPLOAD_DIR.$file);

Code:

Here we need to convert the file size to KB

$kilobytes = MAX_FILE_SIZE/1024;
$formatted = number_format($kilobytes, 1);
$max = $formatted.'KB';

The final code :

// check that file is within the permitted size
if ($_FILES['image']['size'] > 0 && $_FILES['image']['size'] <=
MAX_FILE_SIZE) {
$sizeOK = true;
}
if ($sizeOK) {
switch($_FILES['image']['error']) {
case 0:
// move the file to the upload folder and rename it
$success = move_uploaded_file($_FILES['image']['tmp_name'],
UPLOAD_DIR.$file);
if ($success) {
$result = "$file uploaded successfully";
}
else {
$result = "Error uploading $file. Please try again.";
}
break;
case 3:
$result = "Error uploading $file. Please try again.";
default:
$result = "System error uploading $file. Contact webmaster.";
}
}
elseif ($_FILES['image']['error'] == 4) {
$result = 'No file selected';
}
else {
$result = "$file cannot be uploaded. Maximum size: $max.";
}
}

0 comments:

Post a Comment