PHP returns an appropriate error code along with the
file array. The error code can be found in the
error
segment of the file array that is created
during the file upload by PHP. In other words, the error might be
found in $_FILES[‘userfile’][‘error’].
-
UPLOAD_ERR_OK
-
Value: 0; There is no error, the file uploaded with success.
-
UPLOAD_ERR_INI_SIZE
-
Value: 1; The uploaded file exceeds the
upload_max_filesize
directive in php.ini. -
UPLOAD_ERR_FORM_SIZE
-
Value: 2; The uploaded file exceeds the MAX_FILE_SIZE
directive that was specified in the HTML form. -
UPLOAD_ERR_PARTIAL
-
Value: 3; The uploaded file was only partially uploaded.
-
UPLOAD_ERR_NO_FILE
-
Value: 4; No file was uploaded.
-
UPLOAD_ERR_NO_TMP_DIR
-
Value: 6; Missing a temporary folder.
-
UPLOAD_ERR_CANT_WRITE
-
Value: 7; Failed to write file to disk.
-
UPLOAD_ERR_EXTENSION
-
Value: 8; A PHP extension stopped the file upload. PHP does not
provide a way to ascertain which extension caused the file upload to
stop; examining the list of loaded extensions with phpinfo() may help.
Viktor ¶
8 years ago
Update to Adams old comment.
This is probably useful to someone.
<?php
$phpFileUploadErrors
= array(
0 => 'There is no error, the file uploaded with success',
1 => 'The uploaded file exceeds the upload_max_filesize directive in php.ini',
2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
3 => 'The uploaded file was only partially uploaded',
4 => 'No file was uploaded',
6 => 'Missing a temporary folder',
7 => 'Failed to write file to disk.',
8 => 'A PHP extension stopped the file upload.',
);
Anonymous ¶
13 years ago
[EDIT BY danbrown AT php DOT net: This code is a fixed version of a note originally submitted by (Thalent, Michiel Thalen) on 04-Mar-2009.]
This is a handy exception to use when handling upload errors:
<?php
class UploadException extends Exception
{
public function __construct($code) {
$message = $this->codeToMessage($code);
parent::__construct($message, $code);
}
private function
codeToMessage($code)
{
switch ($code) {
case UPLOAD_ERR_INI_SIZE:
$message = "The uploaded file exceeds the upload_max_filesize directive in php.ini";
break;
case UPLOAD_ERR_FORM_SIZE:
$message = "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form";
break;
case UPLOAD_ERR_PARTIAL:
$message = "The uploaded file was only partially uploaded";
break;
case UPLOAD_ERR_NO_FILE:
$message = "No file was uploaded";
break;
case UPLOAD_ERR_NO_TMP_DIR:
$message = "Missing a temporary folder";
break;
case UPLOAD_ERR_CANT_WRITE:
$message = "Failed to write file to disk";
break;
case UPLOAD_ERR_EXTENSION:
$message = "File upload stopped by extension";
break;
default:
$message = "Unknown upload error";
break;
}
return $message;
}
}
// Use
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
//uploading successfully done
} else {
throw new UploadException($_FILES['file']['error']);
}
?>
adam at gotlinux dot us ¶
17 years ago
This is probably useful to someone.
<?php
array(
0=>"There is no error, the file uploaded with success",
1=>"The uploaded file exceeds the upload_max_filesize directive in php.ini",
2=>"The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"
3=>"The uploaded file was only partially uploaded",
4=>"No file was uploaded",
6=>"Missing a temporary folder"
);
?>
stephen at poppymedia dot co dot uk ¶
17 years ago
if post is greater than post_max_size set in php.ini
$_FILES and $_POST will return empty
svenr at selfhtml dot org ¶
15 years ago
Clarification on the MAX_FILE_SIZE hidden form field and the UPLOAD_ERR_FORM_SIZE error code:
PHP has the somewhat strange feature of checking multiple "maximum file sizes".
The two widely known limits are the php.ini settings "post_max_size" and "upload_max_size", which in combination impose a hard limit on the maximum amount of data that can be received.
In addition to this PHP somehow got implemented a soft limit feature. It checks the existance of a form field names "max_file_size" (upper case is also OK), which should contain an integer with the maximum number of bytes allowed. If the uploaded file is bigger than the integer in this field, PHP disallows this upload and presents an error code in the $_FILES-Array.
The PHP documentation also makes (or made - see bug #40387 - http://bugs.php.net/bug.php?id=40387) vague references to "allows browsers to check the file size before uploading". This, however, is not true and has never been. Up til today there has never been a RFC proposing the usage of such named form field, nor has there been a browser actually checking its existance or content, or preventing anything. The PHP documentation implies that a browser may alert the user that his upload is too big - this is simply wrong.
Please note that using this PHP feature is not a good idea. A form field can easily be changed by the client. If you have to check the size of a file, do it conventionally within your script, using a script-defined integer, not an arbitrary number you got from the HTTP client (which always must be mistrusted from a security standpoint).
jalcort at att dot net ¶
3 years ago
When uploading a file, it is common to visit the php.ini and set up upload_tmp_dir = /temp but in the case of some web hostess as fatcow you need to direct not only /tmp but upload_tmp_dir = /hermes/walnaweb13a/b345/moo.youruser/tmp
If not the $_FILES show you an error #6 "Missing a temporary folder
roland at REMOVE_ME dot mxchange dot org ¶
4 years ago
I have expanded @adam at gotlinux dot us's example a bit with proper UPLOAD_FOO constants and gettext support. Also UPLOAD_ERR_EXTENSION is added (was missing in his version). Hope this helps someone.
<?php
class Some {
/**
* Upload error codes
* @var array
*/
private static $upload_errors = [];
public function
__construct() {
// Init upload errors
self::$upload_errors = [
UPLOAD_ERR_OK => _('There is no error, the file uploaded with success.'),
UPLOAD_ERR_INI_SIZE => _('The uploaded file exceeds the upload_max_filesize directive in php.ini.'),
UPLOAD_ERR_FORM_SIZE => _('The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.'),
UPLOAD_ERR_PARTIAL => _('The uploaded file was only partially uploaded.'),
UPLOAD_ERR_NO_FILE => _('No file was uploaded.'),
UPLOAD_ERR_NO_TMP_DIR => _('Missing a temporary folder.'),
UPLOAD_ERR_CANT_WRITE => _('Cannot write to target directory. Please fix CHMOD.'),
UPLOAD_ERR_EXTENSION => _('A PHP extension stopped the file upload.'),
];
}
}
?>
Jeff Miner mrjminer AT gmail DOT com ¶
12 years ago
One thing that is annoying is that the way these constant values are handled requires processing no error with the equality, which wastes a little bit of space. Even though "no error" is 0, which typically evaluates to "false" in an if statement, it will always evaluate to true in this context.
So, instead of this:
-----
<?php
if($_FILES['userfile']['error']) {
// handle the error
} else {
// process
}
?>
-----
You have to do this:
-----
<?php
if($_FILES['userfile']['error']==0) {
// process
} else {
// handle the error
}
?>
-----
Also, ctype_digit fails, but is_int works. If you're wondering... no, it doesn't make any sense.
To Schoschie:
You ask the question: Why make stuff complicated when you can make it easy? I ask the same question since the version of the code you / Anonymous / Thalent (per danbrown) have posted is unnecessary overhead and would result in a function call, as well as a potentially lengthy switch statement. In a loop, that would be deadly... try this instead:
-----
<?php
$error_types = array(
1=>'The uploaded file exceeds the upload_max_filesize directive in php.ini.',
'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.',
'The uploaded file was only partially uploaded.',
'No file was uploaded.',
6=>'Missing a temporary folder.',
'Failed to write file to disk.',
'A PHP extension stopped the file upload.'
);
// Outside a loop...
if($_FILES['userfile']['error']==0) {
// process
} else {
$error_message = $error_types[$_FILES['userfile']['error']];
// do whatever with the error message
}
// In a loop...
for($x=0,$y=count($_FILES['userfile']['error']);$x<$y;++$x) {
if($_FILES['userfile']['error'][$x]==0) {
// process
} else {
$error_message = $error_types[$_FILES['userfile']['error'][$x]];
// Do whatever with the error message
}
}
// When you're done... if you aren't doing all of this in a function that's about to end / complete all the processing and want to reclaim the memory
unset($error_types);
?>
jille at quis dot cx ¶
13 years ago
UPLOAD_ERR_PARTIAL is given when the mime boundary is not found after the file data. A possibly cause for this is that the upload was cancelled by the user (pressed ESC, etc).
sysadmin at cs dot fit dot edu ¶
17 years ago
I noticed that on PHP-4.3.2 that $_FILES can also not be set if the file uploaded exceeds the limits set by upload-max-filesize in the php.ini, rather than setting error $_FILES["file"]["error"]
tyler at fishmas dot org ¶
18 years ago
In regards to the dud filename being sent, a very simple way to check for this is to check the file size as well as the file name. For example, to check the file size simple use the size attribute in your file info array:
<?php
if($_FILES["file_id"]["size"] == 0)
{
// ...PROCESS ERROR
}
?>
Tom ¶
12 years ago
Note: something that might surprise you, PHP also provides a value in the $_FILES array, if the input element has no value at all, stating an error UPLOAD_ERR_NO_FILE.
So UPLOAD_ERR_NO_FILE is not an error, but a note that the input element just had no value. Thus you can't rely on the $_FILES array to see if a file was provided. Instead you have to walk the array and check every single damn entry - which can be quite difficult since the values may be nested if you use input elements named like "foo[bar][bla]".
Seems like PHP just introduced you to yet another common pitfall.
admin at compumatter dot com ¶
3 years ago
We use this function to handle file uploads.
Since $_FILES allows for more than a single file, this loops through each file and if there's an error, it is displayed in human readable language to the error log and then returned / exited. You can adjust that to echo's if preferred:
function file_upload_test($messageBefore="CM FILE UPLOAD MESSAGE"){
global $_FILES;
# a single file limit
$upload_max_size = ini_get('upload_max_filesize');
# the combination of a batch o multiple files
$post_max_size = ini_get('post_max_size');
# array of possible fails which are retuned below in if $key=error section
$phpFileUploadErrors = array(
0 => 'There is no error, the file uploaded with success',
1 => 'Exceeds php.ini upload_max_filesize of '.$upload_max_size.'MB',
2 => 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form',
3 => 'The uploaded file was only partially uploaded',
4 => 'No file was uploaded',
6 => 'Missing a temporary folder',
7 => 'Failed to write file to disk.',
8 => 'A PHP extension stopped the file upload.',
);
error_log("========================================");
error_log("$messageBefore");
error_log("========================================");
foreach ($_FILES['cmmediabrowsedfor'] as $key => $value) {
${$key}=$value;
error_log('$_FILES ['.$key.'] = ['.$value.']');
if(is_array($value)){
foreach ($value as $key2 => $value2) {
error_log(' > $_FILES ['.$key.']['.$key2.'] = '.$value2);
if($key=='error'){
error_log(' ******* CM Failed Upload: '.$phpFileUploadErrors[$value2]);
error_log(' Exit / Return in plugins/cm-alpha/php/images/img-create-tmp.php');
error_log(' ');
exit;
}
}
}
}
if(!file_exists($_FILES["cmmediabrowsedfor"]["tmp_name"][0]) || !is_uploaded_file($_FILES["cmmediabrowsedfor"]["tmp_name"][0])) {
error_log("NO FILE GOT UPLOADED ");
} else {
error_log("SUCCESS FILE GOT UPLOADED ");
}
}
rlerne at gmail dot com ¶
8 years ago
This updates "adam at gotlinux dot us" above and makes it version aware, and also adds newer constants to the array.
The reason we want to check the version is that the constants are not defined in earlier versions, and they appear later in the array. They would effectively overwrite the "0" index (no error) with an error message when the file actually uploaded fine.
It also drops the constant's value (0,1,2, etc) for the errors, in the likely event that they are changed later (the code should still work fine).
<?php
$upload_errors
= array(
0 => "There is no error, the file uploaded with success"
,UPLOAD_ERR_INI_SIZE => "The uploaded file exceeds the upload_max_filesize directive in php.ini"
,UPLOAD_ERR_FORM_SIZE => "The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form"
,UPLOAD_ERR_PARTIAL => "The uploaded file was only partially uploaded"
,UPLOAD_ERR_NO_FILE => "No file was uploaded"
);
if (
version_compare(PHP_VERSION, '5.0.3') >= 0)
$upload_errors[UPLOAD_ERR_NO_TMP_DIR] = "Missing a temporary folder";
if (
version_compare(PHP_VERSION, '5.1.0') >= 0)
$upload_errors[UPLOAD_ERR_CANT_WRITE] = "Failed to write to disk";
if (
version_compare(PHP_VERSION, '5.2.0') >= 0)
$upload_errors[UPLOAD_ERR_EXTENSION] = "File upload stopped by extension";
?>
belowtherim2000 at yahoo dot com ¶
15 years ago
I've been playing around with the file size limits and with respect to the post_max_size setting, there appears to be a hard limit of 2047M. Any number that you specify above that results in a failed upload without any informative error describing what went wrong. This happens regardless of how small the file you're uploading may be. On error, my page attempts to output the name of the original file. But what I discovered is that this original file name, which I maintained in a local variable, actually gets corrupted. Even my attempt to output the error code in $_FILES['uploadedfiles']['error'] returns an empty string/value.
Hopefully, this tidbit will save someone else some grief.
viseth10 at gmail dot com ¶
5 years ago
[Well just a little note. ]
That UploadException class example posted on top by anonymous is great. It works good. But there is a certain problem. You know there are two sides to generating errors.
First -> for the client side.
Second -> for the developers who will use your script
But i see only one side to generating Exceptions. ie For the developers.
Why ? Because when you generate an Exception, your script will come to an halt and do whatever you have defined in catch clause.
Now you dont want any client to see the Exception, do you ? I will not. The client will want to know what error occured in simple words they can understand instead of wanting their web app crashed if upload fails. So, dont generate exceptions. These errors should be collected and shown to client in an elegant way. That's a little advice.
Keep developing smarter.
krissv at ifi.uio.no ¶
18 years ago
When $_FILES etc is empty like Dub spencer says in the note at the top and the error is not set, that might be because the form enctype isnt sat correctly. then nothing more than maybe a http server error happens.
enctype="multipart/form-data" works fine
roger dot vermeir at nokia dot com ¶
4 years ago
Just found out that it is very important to define the
input type="hidden" name="MAX_FILE_SIZE" value=...
AFTER defining the input type="FILE" name=...
in your html/php.
If you swap them around, you will keep getting the filesize exceeded (error 2)!
Hope this helps.
Roger
Dub Spencer ¶
18 years ago
Upload doesnt work, and no error?
actually, both $_FILES and $_REQUEST in the posted to script are empty?
just see, if "post_max_size" is lower than the data you want to load.
in the apache error log, there will be an entry like "Invalid method in request". and in the access log, there will be two requests: one for the POST, and another that starts with all "----" and produces a 501.
web att lapas dott id dott lv ¶
15 years ago
1. And what about multiple file upload ? - If there is an UPLOAD_ERR_INI_SIZE error with multiple files - we can`t detect it normaly ? ...because that we have an array, but this error returns null and can`t use foreach. So, by having a multiple upload, we can`t normaly inform user about that.. we can just detect, that sizeof($_FILES["file"]["error"]) == 0 , but we can`t actualy return an error code. The max_file_size also is not an exit, becouse it refers on each file seperatly, but upload_max_filesize directive in php.ini refers to all files together. So, for example, if upload_max_filesize=8Mb , max_file_size = 7Mb and one of my files is 6.5Mb and other is 5Mb, it exeeds the upload_max_filesize - cant return an error, becouse we don`t know where to get that error.
Unfortunately we cannot get the file sizes on client side, even AJAX normaly can`t do that.
2. If in file field we paste something, like, D:whatever , then there also isn`t an error to return in spite of that no such file at all.
info at foto50 dot com ¶
15 years ago
For those reading this manual in german (and/or probably some other languages) and you miss error numbers listed here, have a look to the english version of this page ;)
Tom ¶
8 years ago
As it is common to use move_uploaded_file with file uploads, how to get it's error messages should be noted here (especially since it's not noted anywhere else in the manual).
Common code is to do something like:
if (move_uploaded_file($_FILES["file1"]["tmp_name"], $target_file)) {
echo "<P>FILE UPLOADED TO: $target_file</P>";
} else {
echo "<P>MOVE UPLOADED FILE FAILED!!</P>";
print_r(error_get_last());
}
Содержание
- Разъяснение сообщений об ошибках
- Php files file error code
- Массив $_FILES
- Загрузка одного файла
- Код скрипта index.php:
- Результат:
- Загрузка несколько файлов
- Код скрипта index.php
- Результат:
- Результат:
- Максимальный размер загружаемого файла
- Коды ошибок загрузки файлов
- Настройки PHP
- Handling file uploads
- Table of Contents
- User Contributed Notes 32 notes
Разъяснение сообщений об ошибках
PHP возвращает код ошибки наряду с другими атрибутами принятого файла. Он расположен в массиве, создаваемом PHP при загрузке файла, и может быть получен при обращении по ключу error. Говоря другими словами, код ошибки можно найти в переменной $_FILES[‘userfile’][‘error’] .
UPLOAD_ERR_OK
Значение: 0; Ошибок не возникло, файл был успешно загружен на сервер.
UPLOAD_ERR_INI_SIZE
Значение: 1; Размер принятого файла превысил максимально допустимый размер, который задан директивой upload_max_filesize конфигурационного файла php.ini .
UPLOAD_ERR_FORM_SIZE
Значение: 2; Размер загружаемого файла превысил значение MAX_FILE_SIZE, указанное в HTML-форме.
UPLOAD_ERR_PARTIAL
Значение: 3; Загружаемый файл был получен только частично.
UPLOAD_ERR_NO_FILE
Значение: 4; Файл не был загружен.
UPLOAD_ERR_NO_TMP_DIR
Значение: 6; Отсутствует временная папка. Добавлено в PHP 5.0.3.
UPLOAD_ERR_CANT_WRITE
Значение: 7; Не удалось записать файл на диск. Добавлено в PHP 5.1.0.
UPLOAD_ERR_EXTENSION
Значение: 8; PHP-расширение остановило загрузку файла. PHP не предоставляет способа определить какое расширение остановило загрузку файла; в этом может помочь просмотр списка загруженных расширений из phpinfo() . Добавлено в PHP 5.2.0.
Источник
Php files file error code
$_FILES and $_POST will return empty
Clarification on the MAX_FILE_SIZE hidden form field and the UPLOAD_ERR_FORM_SIZE error code:
PHP has the somewhat strange feature of checking multiple «maximum file sizes».
The two widely known limits are the php.ini settings «post_max_size» and «upload_max_size», which in combination impose a hard limit on the maximum amount of data that can be received.
In addition to this PHP somehow got implemented a soft limit feature. It checks the existance of a form field names «max_file_size» (upper case is also OK), which should contain an integer with the maximum number of bytes allowed. If the uploaded file is bigger than the integer in this field, PHP disallows this upload and presents an error code in the $_FILES-Array.
The PHP documentation also makes (or made — see bug #40387 — http://bugs.php.net/bug.php?id=40387) vague references to «allows browsers to check the file size before uploading». This, however, is not true and has never been. Up til today there has never been a RFC proposing the usage of such named form field, nor has there been a browser actually checking its existance or content, or preventing anything. The PHP documentation implies that a browser may alert the user that his upload is too big — this is simply wrong.
Please note that using this PHP feature is not a good idea. A form field can easily be changed by the client. If you have to check the size of a file, do it conventionally within your script, using a script-defined integer, not an arbitrary number you got from the HTTP client (which always must be mistrusted from a security standpoint).
When uploading a file, it is common to visit the php.ini and set up upload_tmp_dir = /temp but in the case of some web hostess as fatcow you need to direct not only /tmp but upload_tmp_dir = /hermes/walnaweb13a/b345/moo.youruser/tmp
If not the $_FILES show you an error #6 «Missing a temporary folder
I have expanded @adam at gotlinux dot us’s example a bit with proper UPLOAD_FOO constants and gettext support. Also UPLOAD_ERR_EXTENSION is added (was missing in his version). Hope this helps someone.
class Some <
/**
* Upload error codes
* @var array
*/
private static $upload_errors = [];
public function __construct () <
// Init upload errors
self :: $upload_errors = [
UPLOAD_ERR_OK => _ ( ‘There is no error, the file uploaded with success.’ ),
UPLOAD_ERR_INI_SIZE => _ ( ‘The uploaded file exceeds the upload_max_filesize directive in php.ini.’ ),
UPLOAD_ERR_FORM_SIZE => _ ( ‘The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.’ ),
UPLOAD_ERR_PARTIAL => _ ( ‘The uploaded file was only partially uploaded.’ ),
UPLOAD_ERR_NO_FILE => _ ( ‘No file was uploaded.’ ),
UPLOAD_ERR_NO_TMP_DIR => _ ( ‘Missing a temporary folder.’ ),
UPLOAD_ERR_CANT_WRITE => _ ( ‘Cannot write to target directory. Please fix CHMOD.’ ),
UPLOAD_ERR_EXTENSION => _ ( ‘A PHP extension stopped the file upload.’ ),
];
>
>
?>
One thing that is annoying is that the way these constant values are handled requires processing no error with the equality, which wastes a little bit of space. Even though «no error» is 0, which typically evaluates to «false» in an if statement, it will always evaluate to true in this context.
So, instead of this:
——
if( $_FILES [ ‘userfile’ ][ ‘error’ ]) <
// handle the error
> else <
// process
>
?>
——
You have to do this:
——
if( $_FILES [ ‘userfile’ ][ ‘error’ ]== 0 ) <
// process
> else <
// handle the error
>
?>
——
Also, ctype_digit fails, but is_int works. If you’re wondering. no, it doesn’t make any sense.
You ask the question: Why make stuff complicated when you can make it easy? I ask the same question since the version of the code you / Anonymous / Thalent (per danbrown) have posted is unnecessary overhead and would result in a function call, as well as a potentially lengthy switch statement. In a loop, that would be deadly. try this instead:
——
= array(
1 => ‘The uploaded file exceeds the upload_max_filesize directive in php.ini.’ ,
‘The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML form.’ ,
‘The uploaded file was only partially uploaded.’ ,
‘No file was uploaded.’ ,
6 => ‘Missing a temporary folder.’ ,
‘Failed to write file to disk.’ ,
‘A PHP extension stopped the file upload.’
);
// Outside a loop.
if( $_FILES [ ‘userfile’ ][ ‘error’ ]== 0 ) <
// process
> else <
$error_message = $error_types [ $_FILES [ ‘userfile’ ][ ‘error’ ]];
// do whatever with the error message
>
// In a loop.
for( $x = 0 , $y = count ( $_FILES [ ‘userfile’ ][ ‘error’ ]); $x $y ;++ $x ) <
if( $_FILES [ ‘userfile’ ][ ‘error’ ][ $x ]== 0 ) <
// process
> else <
$error_message = $error_types [ $_FILES [ ‘userfile’ ][ ‘error’ ][ $x ]];
// Do whatever with the error message
>
>
// When you’re done. if you aren’t doing all of this in a function that’s about to end / complete all the processing and want to reclaim the memory
unset( $error_types );
?>
Источник
Массив $_FILES
В PHP-скрипте обработка загруженных через форму происходит через глобальный массив $_FILES , рассмотрим его содержимое:
Загрузка одного файла
Чтобы форма отправила файл, необходимо использовать только метод POST для отправки данных и добавить к тегу
Код скрипта index.php:
Результат:
Описание значений массива $_FILES :
$_FILES[‘file-1’][‘name’] | Оригинальное имя файла на компьютере клиента. |
$_FILES[‘file-1’][‘type’] | Mime-тип файла, в случае, если браузер предоставил такую информацию. Этот mime-тип не проверяется на стороне PHP, так что не полагайтесь на его значение без проверки. |
$_FILES[‘file-1’][‘size’] | Размер принятого файла в байтах . |
$_FILES[‘file-1’][‘tmp_name’] | Временное имя, с которым принятый файл был сохранен на сервере. |
$_FILES[‘file-1’][‘error’] | Код ошибки, которая может возникнуть при загрузке файла. |
Загрузка несколько файлов
Для загрузки сразу нескольких файлов к нужно добавить атрибут multiple , а к имени поля – [] .
Код скрипта index.php
Результат:
Как видно, структура массива разделена по свойствам, а не по файлам. Для удобства работы с циклом foreach массив $_FILES можно преобразовать:
Результат:
Максимальный размер загружаемого файла
Размер загружаемого файла можно ограничить, добавив в форму скрытое поле с максимальным размером файла :
В случае превышения размера файла в переменной $_FILES[‘file-1’][‘error’] будет ошибка с кодом « 2 ».
Коды ошибок загрузки файлов
В случаи, если при загрузке файла произошла ошибка, в переменной $_FILES[‘file’][‘error’] будет содержатся её код. Возможны следующие значения:
Код | Константа | Описание |
---|---|---|
UPLOAD_ERR_OK | Ошибок не возникло, файл успешно загружен на сервер. | |
1 | UPLOAD_ERR_INI_SIZE | Размер файла превысил максимально допустимый размер, который задан директивой upload_max_filesize |
2 | UPLOAD_ERR_FORM_SIZE | Размер загружаемого файла превысил значение MAX_FILE_SIZE, указанное в HTML-форме. |
3 | UPLOAD_ERR_PARTIAL | Загружаемый файл был получен только частично. |
4 | UPLOAD_ERR_NO_FILE | Файл не был загружен. |
6 | UPLOAD_ERR_NO_TMP_DIR | Отсутствует временная папка. |
7 | UPLOAD_ERR_CANT_WRITE | Не удалось записать файл на диск (возникает, когда на хостинге закончилось место). |
8 | UPLOAD_ERR_EXTENSION | PHP-расширение остановило загрузку файла. |
Настройки PHP
Обычно настройки загрузки файлов на хостинге вполне нормальные и не вызывают проблем, но есть исключения. Если не загружаются большие файлы, то скорее всего установлен лимит на размер загружаемого файла, ограничено время загрузки файла или ограничено количество одновременных загрузок.
Посмотреть установленные значения можно с помощью функции phpinfo() , в разделе «Core».
Источник
Handling file uploads
Table of Contents
User Contributed Notes 32 notes
You’d better check $_FILES structure and values throughly.
The following code cannot cause any errors absolutely.
Example:
( ‘Content-Type: text/plain; charset=utf-8’ );
// Undefined | Multiple Files | $_FILES Corruption Attack
// If this request falls under any of them, treat it invalid.
if (
!isset( $_FILES [ ‘upfile’ ][ ‘error’ ]) ||
is_array ( $_FILES [ ‘upfile’ ][ ‘error’ ])
) <
throw new RuntimeException ( ‘Invalid parameters.’ );
>
// Check $_FILES[‘upfile’][‘error’] value.
switch ( $_FILES [ ‘upfile’ ][ ‘error’ ]) <
case UPLOAD_ERR_OK :
break;
case UPLOAD_ERR_NO_FILE :
throw new RuntimeException ( ‘No file sent.’ );
case UPLOAD_ERR_INI_SIZE :
case UPLOAD_ERR_FORM_SIZE :
throw new RuntimeException ( ‘Exceeded filesize limit.’ );
default:
throw new RuntimeException ( ‘Unknown errors.’ );
>
// You should also check filesize here.
if ( $_FILES [ ‘upfile’ ][ ‘size’ ] > 1000000 ) <
throw new RuntimeException ( ‘Exceeded filesize limit.’ );
>
// DO NOT TRUST $_FILES[‘upfile’][‘mime’] VALUE !!
// Check MIME Type by yourself.
$finfo = new finfo ( FILEINFO_MIME_TYPE );
if ( false === $ext = array_search (
$finfo -> file ( $_FILES [ ‘upfile’ ][ ‘tmp_name’ ]),
array(
‘jpg’ => ‘image/jpeg’ ,
‘png’ => ‘image/png’ ,
‘gif’ => ‘image/gif’ ,
),
true
)) <
throw new RuntimeException ( ‘Invalid file format.’ );
>
// You should name it uniquely.
// DO NOT USE $_FILES[‘upfile’][‘name’] WITHOUT ANY VALIDATION !!
// On this example, obtain safe unique name from its binary data.
if (! move_uploaded_file (
$_FILES [ ‘upfile’ ][ ‘tmp_name’ ],
sprintf ( ‘./uploads/%s.%s’ ,
sha1_file ( $_FILES [ ‘upfile’ ][ ‘tmp_name’ ]),
$ext
)
)) <
throw new RuntimeException ( ‘Failed to move uploaded file.’ );
>
echo ‘File is uploaded successfully.’ ;
> catch ( RuntimeException $e ) <
echo $e -> getMessage ();
IE on the Mac is a bit troublesome. If you are uploading a file with an unknown file suffix, IE uploads the file with a mime type of «application/x-macbinary». The resulting file includes the resource fork wrapped around the file. Not terribly useful.
The following code assumes that the mime type is in $type, and that you have loaded the file’s contents into $content. If the file is in MacBinary format, it delves into the resource fork header, gets the length of the data fork (bytes 83-86) and uses that to get rid of the resource fork.
(There is probably a better way to do it, but this solved my problem):
if ( $type == ‘application/x-macbinary’ ) <
if ( strlen ( $content ) 128 ) die( ‘File too small’ );
$length = 0 ;
for ( $i = 83 ; $i 86 ; $i ++) <
$length = ( $length * 256 ) + ord ( substr ( $content , $i , 1 ));
>
$content = substr ( $content , 128 , $length );
>
?>
Clarification on the MAX_FILE_SIZE hidden form field:
PHP has the somewhat strange feature of checking multiple «maximum file sizes».
The two widely known limits are the php.ini settings «post_max_size» and «upload_max_size», which in combination impose a hard limit on the maximum amount of data that can be received.
In addition to this PHP somehow got implemented a soft limit feature. It checks the existance of a form field names «max_file_size» (upper case is also OK), which should contain an integer with the maximum number of bytes allowed. If the uploaded file is bigger than the integer in this field, PHP disallows this upload and presents an error code in the $_FILES-Array.
The PHP documentation also makes (or made — see bug #40387 — http://bugs.php.net/bug.php?id=40387) vague references to «allows browsers to check the file size before uploading». This, however, is not true and has never been. Up til today there has never been a RFC proposing the usage of such named form field, nor has there been a browser actually checking its existance or content, or preventing anything. The PHP documentation implies that a browser may alert the user that his upload is too big — this is simply wrong.
Please note that using this PHP feature is not a good idea. A form field can easily be changed by the client. If you have to check the size of a file, do it conventionally within your script, using a script-defined integer, not an arbitrary number you got from the HTTP client (which always must be mistrusted from a security standpoint).
From the manual:
If no file is selected for upload in your form, PHP will return $_FILES[‘userfile’][‘size’] as 0, and $_FILES[‘userfile’][‘tmp_name’] as none.
As of PHP 4.2.0, the «none» is no longer a reliable determinant of no file uploaded. It’s documented if you click on the «error codes» link, but you need to look at the $_FILES[‘your_file’][‘error’]. If it’s 4, then no file was selected.
If «large files» (ie: 50 or 100 MB) fail, check this:
It may happen that your outgoing connection to the server is slow, and it may timeout not the «execution time» but the «input time», which for example in our system defaulted to 60s. In our case a large upload could take 1 or 2 hours.
Additionally we had «session settings» that should be preserved after upload.
1) You might want review those ini entries:
* session.gc_maxlifetime
* max_input_time
* max_execution_time
* upload_max_filesize
* post_max_size
2) Still fails? Caution, not all are changeable from the script itself. ini_set() might fail to override.
You can see that the «upload_max_filesize», among others, is PHP_INI_PERDIR and not PHP_INI_ALL. This invalidates to use ini_set():
http://www.php.net/manual/en/configuration.changes.modes.php
Use .htaccess instead.
3) Still fails?. Just make sure you enabled «.htaccess» to overwrite your php settings. This is made in the apache file. You need at least AllowOverride Options.
You will necessarily allow this manually in the case your master files come with AllowOverride None.
Depending on the system, to allow «large file uploads» you must go up and up and up and touch your config necessarily up to the apache config.
These work for me, for 100MB uploads, lasting 2 hours:
In .htaccess:
————————————————————
php_value session.gc_maxlifetime 10800
php_value max_input_time 10800
php_value max_execution_time 10800
php_value upload_max_filesize 110M
php_value post_max_size 120M
————————————————————
In the example,
— As I last 1 to 2 hours, I allow 3 hours (3600×3)
— As I need 100MB, I allow air above for the file (110M) and a bit more for the whole post (120M).
Caution: *DO NOT* trust $_FILES[‘userfile’][‘type’] to verify the uploaded filetype; if you do so your server could be compromised. I’ll show you why below:
The manual (if you scroll above) states: $_FILES[‘userfile’][‘type’] — The mime type of the file, if the browser provided this information. An example would be «image/gif».
Be reminded that this mime type can easily be faked as PHP doesn’t go very far in verifying whether it really is what the end user reported!
So, someone could upload a nasty .php script as an «image/gif» and execute the url to the «image».
My best bet would be for you to check the extension of the file and using exif_imagetype() to check for valid images. Many people have suggested the use of getimagesize() which returns an array if the file is indeed an image and false otherwise, but exif_imagetype() is much faster. (the manual says it so)
Using /var/www/uploads in the example code is just criminal, imnsho.
One should *NOT* upload untrusted files into your web tree, on any server.
Nor should any directory within your web tree have permissions sufficient for an upload to succeed, on a shared server. Any other user on that shared server could write a PHP script to dump anything they want in there!
The $_FILES[‘userfile’][‘type’] is essentially USELESS.
A. Browsers aren’t consistent in their mime-types, so you’ll never catch all the possible combinations of types for any given file format.
B. It can be forged, so it’s crappy security anyway.
One’s code should INSPECT the actual file to see if it looks kosher.
For example, images can quickly and easily be run through imagegetsize and you at least know the first N bytes LOOK like an image. That doesn’t guarantee it’s a valid image, but it makes it much less likely to be a workable security breaching file.
For Un*x based servers, one could use exec and ‘file’ command to see if the Operating System thinks the internal contents seem consistent with the data type you expect.
I’ve had trouble in the past with reading the ‘/tmp’ file in a file upload. It would be nice if PHP let me read that file BEFORE I tried to move_uploaded_file on it, but PHP won’t, presumably under the assumption that I’d be doing something dangerous to read an untrusted file. Fine. One should move the uploaded file to some staging directory. Then you check out its contents as thoroughly as you can. THEN, if it seems kosher, move it into a directory outside your web tree. Any access to that file should be through a PHP script which reads the file. Putting it into your web tree, even with all the checks you can think of, is just too dangerous, imnsho.
There are more than a few User Contributed notes here with naive (bad) advice. Be wary.
Источник
Данная возможность позволяет загружать как текстовые, так и
бинарные файлы. С помощью PHP-функций авторизации и манипуляции
файлами вы получаете полный контроль над тем, кому разрешено
загружать файлы и что должно быть сделано после их загрузки.
PHP способен получать загруженные файлы из любого браузера,
совместимого со стандартом RFC-1867.
Замечание:
Смежные замечания по конфигурацииТакже ознакомьтесь с описанием директив file_uploads,
upload_max_filesize,
upload_tmp_dir,
post_max_size и
max_input_time конфигурационного
файла php.ini
Также следует заметить, что PHP поддерживает загрузку файлов методом PUT,
который используется в клиентах Netscape Composer
и W3C Amaya. Для получения
более детальной документации обратитесь к разделу
поддержка метода PUT
Пример #1 Форма для загрузки файлов
Страница для загрузки файлов может быть реализована при помощи
специальной формы, которая выглядит примерно так:
<!-- Тип кодирования данных, enctype, ДОЛЖЕН БЫТЬ указан ИМЕННО так --> <form enctype="multipart/form-data" action="__URL__" method="POST"> <!-- Поле MAX_FILE_SIZE должно быть указано до поля загрузки файла --> <input type="hidden" name="MAX_FILE_SIZE" value="30000" /> <!-- Название элемента input определяет имя в массиве $_FILES --> Отправить этот файл: <input name="userfile" type="file" /> <input type="submit" value="Send File" /> </form>
В приведенном выше примере __URL__ необходимо заменить ссылкой
на PHP-скрипт.
Скрытое поле MAX_FILE_SIZE (значение
необходимо указывать в байтах) должно предшествовать полю
для выбора файла, и его значение является максимально
допустимым размером принимаемого файла в PHP.
Рекомендуется всегда использовать эту переменную, так как она
предотвращает тревожное ожидание пользователей при передаче
огромных файлов, только для того, чтобы узнать, что файл
слишком большой и передача фактически не состоялась.
Помните, обойти это ограничение на стороне браузера достаточно
просто, следовательно, вы не должны полагаться на то, что
все файлы большего размера будут блокированы при помощи этой
возможности. Это по большей части удобная возможность для
пользователей клиентской части вашего приложения.
Тем не менее, настройки PHP (на сервере) касательно
максимального размера обойти невозможно.
Замечание:
Также следует убедиться, что в атрибутах формы вы указали
enctype=»multipart/form-data», в противном случае
загрузка файлов на сервер выполняться не будет.
Глобальный массив $_FILES содержит всю информацию о загруженных файлах.
Его содержимое для нашего примера приводится ниже. Обратите внимание, что здесь предполагается
использование имени userfile для поля
выбора файла, как и в приведенном выше примере. На самом деле
имя поля может быть любым.
- $_FILES[‘userfile’][‘name’]
-
Оригинальное имя файла на компьютере клиента.
- $_FILES[‘userfile’][‘type’]
-
Mime-тип файла, в случае, если браузер предоставил такую
информацию. Пример: «image/gif». Этот
mime-тип не проверяется в PHP, так что не полагайтесь
на его значение без проверки. - $_FILES[‘userfile’][‘size’]
-
Размер в байтах принятого файла.
- $_FILES[‘userfile’][‘tmp_name’]
-
Временное имя, с которым принятый файл был сохранен на сервере.
- $_FILES[‘userfile’][‘error’]
-
Код ошибки,
которая может возникнуть при загрузке файла.
По умолчанию принятые файлы сохраняются на сервере в стандартной
временной папке до тех пор, пока не будет задана другая директория при
помощи директивы upload_tmp_dir
конфигурационного файла php.ini. Директорию сервера по умолчанию
можно сменить, установив переменную TMPDIR для
окружения, в котором выполняется PHP. Установка этой переменной при помощи
функции putenv() внутри PHP-скрипта работать
не будет. Эта переменная окружения также может использоваться для того,
чтобы удостовериться, что другие операции также работают с принятыми файлами.
Пример #2 Проверка загружаемых на сервер файлов
Для получения более детальной информации вы можете ознакомиться
с описанием функций is_uploaded_file()
и move_uploaded_file(). Следующий пример
принимает и обрабатывает загруженный при помощи формы файл.
<?php
// В PHP 4.1.0 и более ранних версиях следует использовать $HTTP_POST_FILES
// вместо $_FILES.$uploaddir = '/var/www/uploads/';
$uploadfile = $uploaddir . basename($_FILES['userfile']['name']);
echo
'<pre>';
if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploadfile)) {
echo "Файл корректен и был успешно загружен.n";
} else {
echo "Возможная атака с помощью файловой загрузки!n";
}
echo
'Некоторая отладочная информация:';
print_r($_FILES);
"</pre>";?>
PHP-скрипт, принимающий загруженный файл, должен реализовывать логику,
необходимую для определения дальнейших действий над принятым файлом.
Например, вы можете проверить переменную $_FILES[‘userfile’][‘size’],
чтобы отсечь слишком большие или слишком маленькие файлы. Также вы
можете использовать переменную $_FILES[‘userfile’][‘type’]
для исключения файлов, которые не удовлетворяют критерию касательно
типа файла, однако, принимайте во внимание, что это поле полностью
контролируется клиентом, используйте его только в качестве первой
из серии проверок. Также вы можете использовать
$_FILES[‘userfile’][‘error’] и
коды ошибок
при реализации вашей логики. Независимо от того, какую модель поведения
вы выбрали, вы должны удалить файл из временной папки или переместить его в
другую директорию.
В случае, если при отправке формы файл выбран не был, PHP установит
переменную $_FILES[‘userfile’][‘size’] значением 0, а переменную
$_FILES[‘userfile’][‘tmp_name’] — пустой строкой.
none.
По окончанию работы скрипта, в случае, если принятый файл не был
переименован или перемещен, он будет автоматически удален из временной папки.
Пример #3 Загрузка массива файлов
PHP поддерживает возможность передачи массива из HTML
в том числе и с файлами.
<form action="" method="post" enctype="multipart/form-data"> <p>Изображения: <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="file" name="pictures[]" /> <input type="submit" value="Отправить" /> </p> </form>
<?php
foreach ($_FILES["pictures"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$tmp_name = $_FILES["pictures"]["tmp_name"][$key];
$name = $_FILES["pictures"]["name"][$key];
move_uploaded_file($tmp_name, "data/$name");
}
}
?>
Полоса прогресса загрузки файлов может быть реализована с помощью
«отслеживания прогресса загрузки файлов с помощью сессий».
Вернуться к: Загрузка файлов на сервер
Relike 6 / 6 / 2 Регистрация: 24.04.2013 Сообщений: 260 |
||||||||
1 |
||||||||
07.02.2014, 13:40. Показов 4074. Ответов 12 Метки нет (Все метки)
Здравствуйте, я только начал изучать пхп, пишу простенький загрузчик файлов, но у меня проблема! Немогу определить файлсайз. $_FILES[‘userfile’][‘error’] == 2, при любом значении и при отсутствии MAX_FILE_SIZE. Почему возникает такая проблема? index.php
upload.php
Вывод при загрузке файла с расширением *.sh и весом 3кб: Помогите пожалуйста…
__________________
0 |
Dolphin 813 / 796 / 201 Регистрация: 21.09.2012 Сообщений: 2,656 |
||||
07.02.2014, 14:23 |
2 |
|||
1 |
6 / 6 / 2 Регистрация: 24.04.2013 Сообщений: 260 |
|
07.02.2014, 14:33 [ТС] |
3 |
Dolphin, Выводит 5. Где изменяется этот параметр?
0 |
813 / 796 / 201 Регистрация: 21.09.2012 Сообщений: 2,656 |
|
07.02.2014, 14:37 |
4 |
В php.ini Код php_value upload_max_filesize 5M
1 |
6 / 6 / 2 Регистрация: 24.04.2013 Сообщений: 260 |
|
07.02.2014, 14:40 [ТС] |
5 |
Dolphin, Я установил в .htaccess на 30М но всё равно та-же ошибка Добавлено через 2 минуты
0 |
813 / 796 / 201 Регистрация: 21.09.2012 Сообщений: 2,656 |
|
07.02.2014, 14:41 |
6 |
А оно установилось? php скрипт выводит 30М?
1 |
Relike 6 / 6 / 2 Регистрация: 24.04.2013 Сообщений: 260 |
||||
07.02.2014, 15:14 [ТС] |
7 |
|||
Dolphin, Да именно он Добавлено через 18 минут
Поправил и php.ini и .htaccess … но всё равно не определяет размер.
0 |
Dolphin 813 / 796 / 201 Регистрация: 21.09.2012 Сообщений: 2,656 |
||||||||
07.02.2014, 15:19 |
8 |
|||||||
Не понятно зачем вот эта строка
Выведи инфу и посмотри
1 |
Relike 6 / 6 / 2 Регистрация: 24.04.2013 Сообщений: 260 |
||||
07.02.2014, 15:26 [ТС] |
9 |
|||
Вывод: Почему он выводит сообщение о ошибке?
0 |
Dolphin 813 / 796 / 201 Регистрация: 21.09.2012 Сообщений: 2,656 |
||||||||
07.02.2014, 15:31 |
10 |
|||||||
Решение
Пропустил подчеркивание $_FILES
1 |
6 / 6 / 2 Регистрация: 24.04.2013 Сообщений: 260 |
|
07.02.2014, 15:35 [ТС] |
11 |
Dolphin, Так, теперь он вот до куда дошел: upload_max_filesize = 30M Из-за чего он может не загрузить файл? (Стоит LAMP)
0 |
Dolphin 813 / 796 / 201 Регистрация: 21.09.2012 Сообщений: 2,656 |
||||||||
07.02.2014, 15:43 |
12 |
|||||||
Только на рабочем потом убрать этот else
1 |
Relike 6 / 6 / 2 Регистрация: 24.04.2013 Сообщений: 260 |
||||||||
07.02.2014, 16:13 [ТС] |
13 |
|||||||
Он не загружает файл на сервер, хотя и проходит до конца. Если мне нужно загрузить в дирректорию /var/www/phptesting/quest_day2/upload то нужно записать $_SERVER[‘DOCUMENT_ROOT’].’/phptesting/quest_day2/upload’ ? Добавлено через 2 минуты
Проверяю даже наличие файла, всё равно выводит: Начало загрузки файла… Файл успешно загружен. Почему тогда в папке нет файла? А если я указываю свою директорию :
То выводит только начало загрузки и виснет на этом.. Добавлено через 9 минут
0 |
Источник: www.ibm.com
Автор: Александр Деревянко
Дата: 3 августа 2010 года
Введение
В статье рассмотрены вопросы организации загрузки файлов на сервер с помощью PHP, работы с каталогами и файлами на сервере, запуск программ и использование переменных среды. Все это становится актуальным при необходимости решения задач, связанных с изменением Web-содержимого или предоставления дружественного интерфейса пользователю вместо традиционного ftp или scp.
Также мы рассмотрим создание HTML-формы для интерфейса, реализующего функционал загрузки файлов на сервер.
Код HTML-формы
<html> <head> <title>Администрирование сервера - загрузка новых файлов</title> </head> <body> <h1>Загрузка новых файлов с текстовым содержимым.</h1> <form enctype="multipart/form-data" action="upload.php" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="1000000"> Загрузить файл: <input name="userfile" type="file"> <input type="submit" value="Послать файл"> </form> </body> </html>
Форма содержит поля для ввода имени файла и дает возможность выбора такого файла из числа доступных на локальной машине.
Для посылки данных используется метод POST. Дескриптор <form> содержит атрибут enctype=”multipart/form-data” для указания серверу, что вместе с простой информацией будет посылаться и файл.
Форма содержит поле, указывающее на размер файла в байтах. Она имеет скрытый тип, изменяемый по желанию пользователя, – это размер файла (он должен быть согласован с сервером, у которого тоже есть подобные настройки – см. php.ini).
Поле ввода типа file обязательно, и задается следующим образом: <input name = “userfile” tipe=”file”>. Само имя может быть любым и должно совпадать с именем принимающего данные на стороне сервера сценария PHP.
Нужно отметить, что процедура загрузки файлов на сервер очень проблематична с точки зрения безопасности и требует тщательного слежения за обновлениями версий PHP, выходом и применением всех патчей.
Загружающий PHP-сценарий
Код сценария, принимающего данные формы, имеет вид:
<html> <head> <title>Загрузка...</title> </head> <body> <h1>Загрузка файла...</h1> <?php if ($_FILES['userfile']['error'] > 0) { echo 'Проблема: '; switch ($_FILES['userfile']['error']) { case 1: echo 'размер файла больше upload_max_filesize'; break; case 2: echo 'размер файла больше max_file_size'; break; case 3: echo 'загружена только часть файла'; break; case 4: echo 'файл не загружен'; break; } exit; } // Проверка, имеет ли файл правильный MIME-тип. if ($_FILES['userfile']['type'] != 'text/plain') { echo 'Проблема: файл не является текстовым'; exit; } // помещаем файл туда, куда нужно $upfile = '/uploads/'.$_FILES['userfile']['name']; if ($_FILES['userfile']['tmp_name']) { if (!move_uploaded_file($_FILES['userfile']['tmp_name'], $upfile)) { echo 'Проблема: невозможно переместить файл в каталог назначения'; exit; } } else { echo 'Проблема: возможна атака, использующая загрузку файла. Файл: '; echo $_FILES['userfile']['name']; exit; } echo 'Файл корректно загружен.<br /><br />'; // переформатирование содержимого файла $fp = fopen($upfile, 'r'); $contents = fread($fp, filesize ($upfile)); fclose ($fp); $contents = strip_tags($contents); $fp = fopen($upfile, 'w'); fwrite($fp, $contents); fclose($fp); // вывод загруженного файла echo 'Предварительный просмотр содержимого загруженного файла:<br /><hr />'; echo $contents; echo '<br /><hr />'; ?> </body> </html>
В приведенной программе имена функций и переменных зависят от версии PHP и настроек конфигурации, в частности, от включения настройки register_globals.
При загрузке файл помещается во временное хранилище для файлов Web-сервера. Если файл не переименовать и не переместить до окончания сценария, то он будет удален. Данные для обработки в сценарии хранятся в суперглобальном массиве $_FILES. Его элементы будут сохранены с именем дескриптора <file> из формы. Так как имя элемента формы имеет вид userfile, то содержимое массива $_FILES будет иметь следующие свойства:
- значение в $_FILES[‘userfile’][‘tmp_name’] совпадает с хранилищем временных файлов на Web-сервере;
- значение в $_FILES[‘userfile’][‘name’] представляет собой имя файла в локальной файловой системе пользователя формы;
- значение в $_FILES[‘userfile’][‘size’] определяет размер файла в байтах;
- значение в $_FILES[‘userfile’][‘type’] определяет MIME-тип файла – в нашем случае text/plane;
- значение в $_FILES[‘userfile’][‘error’] определяет код ошибки, которая может возникнуть при загрузке файла.
Теперь есть все данные о том, где находится файл и как он именуется, следовательно, его можно скопировать в более пригодное место, чтобы он не был удален как временный по окончании работы скрипта. При этом удаляются все возможные HTML-дескрипторы и осуществляется перенос файла в рабочий каталог.
Большую часть кода представляют проверки на возможные ошибки, потому что загрузка сопряжена с потенциальным риском, который нужно свести к минимуму.
Сначала проверяется код ошибки, возвращаемый $_FILES[‘userfile’][‘error’]. При этом каждому коду ошибки соответствует своя константа. Перечень возможных констант и соответствующих им кодов ошибок приведен ниже:
- upload_error_ok = 0 – ошибок не было;
- upload_err_ini_size = 1 – размер загружаемого файла превышает максимальное значение, заданное в php.ini директивой upload_max_filesize;
- upload_err_form_size = 2 – размер загруженного файла превышает размер, заданный в HTML-форме;
- upload_err_partial = 3 – загружена только часть файла;
- upload_err_no_file = 4 – файл не загружен совсем.
Работа с каталогами
После загрузки файлов на сервер было бы логичным дать пользователю возможность просматривать их содержимое. Для этого необходимо обеспечить вход в каталоги, куда эти файлы загружаются. Эти вопросы решаются программно на уровне соответствующих системных разрешений. Сценарий, обеспечивающий просмотр каталога с загруженными файлами, представлен ниже и представляет собой PHP-скрипт, помещенный внутрь HTML кода:
<html> <head> <title>Просмотр каталогов</title> </head> <body> <h1>Просмотр</h1> <?php $current_dir = '/uploads/'; $dir = opendir($current_dir); echo "<p>Каталог загрузки: $current_dir</p>"; echo '<p>Содержимое каталога:</p><ul>'; while ($file = readdir($dir)) { echo "<li>$file</li>"; } echo '</ul>'; closedir($dir); ?> </body> </html>
Здесь применяются функции opendir(), closedir(), readdir(). Opendir() открывает каталог для чтения и возвращает дескриптор каталога так же, как и функция fopen(). После того как каталог открыт, можно прочитать имя файла с помощью специального вызова readdir($dir). Если каталог пустой или имя файла определено как «0», то функция возвратит false. Файлы при их выводе не сортируются, поэтому если нужен отсортированный список файлов каталога, то можно прочитать их имена в массив и отсортировать его перед выводом на экран. После завершения работы с каталогом вызывается функция closedir($dir) для его закрытия.
Возможно применение механизма ограничения доступных для просмотра файлов и каталогов, чтобы пользователь мог видеть только то, что ему позволено. Целесообразно, при необходимости, применение функции rewindirdir($dir), которая перемещает указатель чтения имен файлов в начало каталога.
Вместо перечисленных выше функций можно использовать класс dir, предоставляемый библиотекой классов php. В нем есть свойства handle и path, а также методы read(), close(), rewind(), выполняющие точно такие же действия, как и их простые аналоги.
Если имеется путь к файлу, то возможно получение дополнительных сведений об имени каталога и файла. Функции dirname($path) и basename($path) возвращают те части пути, которые соответственно содержат каталог и файл. Эту информацию можно применять для создания структуры каталогов, основанной на осмысленных именах файлов и каталогов.
Функция disk_free_space($path) может включить в список содержимого каталога индикацию свободного места для загружаемых файлов. При передаче этой функции пути к каталогу, она возвращает количество свободного места в байтах в файловых системах UNIX и Windows.
Работа с каталогами
Кроме простого просмотра каталогов, возможны операции по их созданию и удалению средствами PHP. Для этого применяют функции mkdir() и rmdir(). Заметим, что возможности таких манипуляций с каталогами определены только в тех случаях, когда доступ к ним разрешен пользователю, от лица которого выполняется сценарий.
Функция mkdir() принимает два параметра – путь к требуемому каталогу (включая имя создаваемого каталога) и права доступа, назначаемые для создаваемого каталога. Например, запись вида mkdir(“/tmp/testing”, 0777); – в данном примере задаваемые права на каталог совсем не обязательно будут результирующе такими же. В этом случае значение umask инвертируется и комбинируется с помощью операции AND, что и определит окончательное формирование параметров доступа. Например, если umask равна 022, то права доступа получатся в виде 0755. Для учета и предотвращения этого эффекта перед созданием каталога нужно сбросить текущее значение umask следующим образом:
$oldmask = umask(0); mkdir(“/tmp/testing”, 0777); umask($oldmask);
Здесь задействована функция umask(), которая используется для получения нового значения прав доступа и для сброса имеющегося. Она заменяет текущее значение umask переданным ей параметром и возвращает старое значение при вызове ее без параметров. В системе Windows функция не производит никаких действий.
remove() предназначена для удаления каталога и применяется следующим образом:
rmdir(“/tmp/testing”); или rmdir(“c:\tmp\testing”);
В обоих случаях удаляемый каталог должен быть пустым.
Взаимодействие с файловой системой
Помимо функций просмотра и получения информации о каталогах и файлах на Web-сервере и записи информации в них возможно осуществление ряда других операций. Сценарий, реализующий получение дополнительной информации о файлах, имеет вид:
<html> <head> <title>Информация о файле</title> </head> <body> <?php $current_dir = '/uploads/'; $file = basename($file);//удаление информации о каталоге для большей безопасности echo '<h1>Информация о файле: '.$file.'</h1>'; $file = $current_dir.$file; echo '<h2>Данные о файле</h2>'; echo 'Последнее обращение: '.date('j F Y H:i', fileatime($file)).'<br />'; echo 'Последняя модификация: '.date('j F Y H:i', filemtime($file)).'<br />'; $user = posix_getpwuid(fileowner($file)); echo 'Владелец файла: '.$user['name'].'<br />'; $group = posix_getgrid(filegroup($file)); echo 'Группа файла: '.$group['name'].'<br />'; echo 'Права доступа: '.decoct(fileperms($file)).'<br />'; echo 'Тип файла: '.filetype($file).'<br />'; echo 'Размер файла: '.filesize($file).' байтов<br />'; echo '<h2>Статус файла</h2>'; echo 'Каталог: '.(is_dir($file)? 'да' : 'нет').'<br />'; echo 'Исполняемый: '.(is_executable($file)? 'да' : 'нет').'<br />'; echo 'Файл: '.(is_file($file)? 'да' : 'нет').'<br />'; echo 'Ссылка: '.(is_link($file)? 'да' : 'нет').'<br />'; echo 'Разрешено чтение: '.(is_readable($file)? 'да' : 'нет').'<br />'; echo 'Разрешена запись: '.(is_writable($file)? 'да' : 'нет').'<br />'; ?> </body> </html>
При работе этого сценария формируется информация об имени файла, метке времени последней модификации файла или обращения к нему, идентификатор пользователя и группы, права доступа к файлу, тип анализируемого файла, размер файла в байтах, а также тестирование атрибутов файла. Все работы со статусом файла требуют повышенных затрат процессорного времени для своего выполнения, поэтому они кэшируются. Результаты кэширования могут быть очищены с помощью функции clearstatcache().
В общем случае все команды, выполняемые на сервере, могут быть объединены в четыре способа их реализации.
- Функция exec() – ей в качестве аргумента передается командная строка, которую нужно выполнить. Например, exec(“ls –la”); эта функция не имеет непосредственных выходных данных и возвращает последнюю строку результата выполнения команды.
- passthru() – передает свои выходные данные в браузер. Используется при выводе изображения в различных форматах. Не возвращает никакого значения.
- system() – передает в браузер выходные данные команды. Пытается передать выходные данные каждой строки. Это отличает ее от passthru().
- Обратные кавычки – фактически это оператор выполнения команды. Результат выполнения возвращается в виде строки, которую затем можно отобразить в браузере или использовать другим путем.
Если имеют место более сложные запросы, то возможно использование функций popen(), proc_open(), proc_close(), предназначенных для создания внешних процессов и передачи данных по каналам к ним и от них.
Ниже приведен сценарий, содержащий эквивалентные примеры использования всех четырех способов:
<?php chdir('/uploads/'); ///// версия exec echo '<pre>'; // unix exec('ls -la', $result); // windows // exec('dir', $result); foreach ($result as $line) echo "$linen"; echo '</pre>'; echo '<br /><hr /><br />'; ///// версия passthru echo '<pre>'; // unix passthru('ls -la'); // windows // passthru('dir'); echo '</pre>'; echo '<br /><hr /><br />'; ///// версия system echo '<pre>'; // unix $result = system('ls -la'); // windows // $result = system('dir'); echo '</pre>'; echo '<br /><hr /><br />'; ///// версия с обратными кавычками echo '<pre>'; // unix $result = `ls -al`; // windows // $result = `dir`; echo $result; echo '</pre>'; ?>
Один из этих способов может применяться вместо рассмотренного ранее сценария просмотра каталогов. Данный код не является переносимым и не может исполняться в среде Windows. При этом если в текст команды необходимо включать пользовательские данные, то их сначала нужно пропускать через функцию escapeshellcmd(). Это не даст возможности неавторизованным пользователям преднамеренно или случайно исполнять команды в системе Web-сервера. Можно в этих же целях воспользоваться функцией escapeshellarg() для отмены всех аргументов, которые нужно передать команде оболочки.
Взаимодействие с окружением
В арсенал средств PHP входит и возможность взаимодействия с переменными окружения. В этих целях используются функции getenv() и putenv(). Они позволяют соответственно получить и устанавливать эти переменные для дальнейшего использования. Речь идет о среде переменных Web-сервера, в которой выполняется PHP-сценарий.
Список всех переменных окружения можно получить, вызвав функцию phpinfo(). Например, getenv(“HTTP_REFERER”); возвратит URL-адрес страницы, с которой пользователь пришел на текущую.
Возможно устанавливать требуемые значения переменной среды с помощью putenv(), например:
$home = “/home/nobody”; putenv (“ HOME = $home “);
При необходимости можно ограничить список переменных окружения, которые доступны для переустановки пользователями. Для этого можно воспользоваться директивой safe_mode_allowed_env_vars файла php.ini. При работе PHP в безопасном режиме пользователи могут менять только те переменные окружения, которые префиксно перечислены в этой директиве.
Выводы
В статье мы подробно разобрали вопросы использования PHP для организации загрузки файлов на сервер, работы с каталогами и переменными окружения. Далее мы займемся изучением работы с сетевыми протоколами и других сложных для начинающего разработчика аспектов использования PHP.
<h1>Upload File</h1>
<form enctype="multipart/form-data" method="post" action="upload.php">
<input type="hidden" name = "MAX_FILE_SIZE" value="100000000000">
<input type ="file" name="userfile">
<input type = "submit" value="Upload File">
</form>
The php script (upload.php)
<?php
$userfile = $_FILES['userfile']['tmp_name'];
$userfile_name = $_FILES['userfile']['name'];
$userfile_size = $_FILES['userfile']['size'];
$userfile_type = $_FILES['userfile']['type'];
$userfile_error = $_FILES['userfile']['error'];
if($userfile_error>0){
echo 'Problem : ';
switch ($userfile_error)
{
case 1: echo 'File exceeded upload_max_filesize'; break;
case 1: echo 'File exceeded max_File_size'; break;
case 1: echo 'File only partially uploaded'; break;
case 1: echo 'No file uploaded'; break;
}
exit;
}
if ($userfile=='none'){
echo 'No file uploaded';
exit;
}
if ($userfile_size==0){
echo ' Problem : Uploaded file size is zero';
exit;
}
if ($userfile_type!='text/plain'){
echo 'File type is not Text format';
exit;
}
$upfile = '/uploads/'.$userfile;
if (is_uploaded_file($userfile)){
if(!move_uploaded_file($userfile,$upfile)){
echo 'Could not move uploaded file';
exit;
}
}
else {
echo 'Possible File Attack';
exit;
}
echo 'File Uploaded Successfuly<br />';
$fp = fopen($upfile,'r');
$comment = fread ($fp,filesize($upfile));
fclose($fp);
$comment = strip_tags($comment);
$fp = fopen($upfile,'w');
fwrite($fp,$comment);
fclose($fp);
echo ' Preview of uploaded files<br />';
echo $comment;
and i get this error on upload.php
Notice: Undefined index: userfile in C:wampwwwupload.php on line 2
Notice: Undefined index: userfile in C:wampwwwupload.php on line 3
Notice: Undefined index: userfile in C:wampwwwupload.php on line 4
Notice: Undefined index: userfile in C:wampwwwupload.php on line 5
Notice: Undefined index: userfile in C:wampwwwupload.php on line 6
Что такое Upload files, или почему не работает:
copy ("c:imagessample.jpg", "c:uploads sample.jpg ")
Даже если у Вас в распоряжении всего один компьютер, на котором совмещен и сервер и рабочая станция, не стоит забывать о том, что php использует технологию клиент/сервер. Файл, который мы хотим загрузить, как правило, находится на машине клиента, т.е. пользователя, обыкновенного посетителя сайта. Место назначения — сервер. Для того чтобы совершить процесс передачи файла, нам понадобиться следующая форма:
<form enctype="multipart/form-data" action="/upload.php" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="30000"> Send this file: <input name="userfile" type="file"> <input type="submit" value="Send File"> </form>
При этом в поле action должен быть указан URL Вашего php-скрипта, который в дальнейшем будет заниматься обработкой загружаемых файлов. Скрытое поле MAX_FILE_SIZE должно предшествовать полю выбора файла, и содержать максимально допустимый размер файла в байтах. Его назначение — проверка размера файла еще до момента отправки файла на сервер. Это должно избавить пользователя от длительной и безрезультатной загрузки файла на сервер и образования лишнего трафика, но не стоит особо полагаться на это ограничение, так как его легко обойти.
Что происходит, когда пользователь выбрал файл на своем диске, и нажал на кнопку «Send file»? Браузер отсылает файл на сервер, где php-интерпретатор помещает его в свою временную директорию, присваивая ему случайное имя и выполняет скрипт, указанный в поле action.
- Как должен выглядеть upload.php?
- Настройка сервера
- Дополнительные возможности
- Краткий очерк о правах на файлы
- Пример реализации загрузки картинок на сервер.
<?php $uploaddir = '/var/www/wp-content/uploads/'; if (move_uploaded_file($_FILES['userfile']['tmp_name'], $uploaddir.$_FILES['userfile']['name'])) { print "File is valid, and was successfully uploaded."; } else { print "There some errors!"; } ?>
При написании скрипта, возникает естественный вопрос: как получить информацию о загруженном файле и достучаться до самого файла. Если Вы используете PHP версии 4.1.0 и старше, лучше всего будет обратиться к глобальному массиву $_FILES. Для каждого загруженного файла он содержит хеш-массив, со следующими данными:
- $_FILES[‘userfile’][‘name’] — оригинальное имя файла, такое, каким его видел пользователь, выбирая файл;
- $_FILES[‘userfile’][‘type’] — mime/type файла, к примеру, может быть image/gif; это поле полезно сохранить, если Вы хотите предоставлять интерфейс для скачивания загруженных файлов;
- $_FILES[‘userfile’][‘size’] — размер загруженного файла;
- $_FILES[‘userfile’][‘tmp_name’] — полный путь к временному файлу на диске;
- $_FILES[‘userfile’][‘error’] — Начиная с версии 4.2.0, содержит код ошибки, который равен 0, если операция прошла успешно.
Для PHP версии ниже 4.1.0 (Рекомендуется немедленно обновить http://www.php.net/downloads.php) этот массив называется $HTTP_POST_FILES. Не стоит забывать, что в отличие от $_FILES этот массив не является суперглобальным и при обращении к нему, к примеру, из функции, необходимо явно указывать global $HTTP_POST_FILES;
Если в настройках Вашего сервера register_globals=on, будут созданы дополнительные переменные вида $userfile_name, $userfile_type, $userfile_size… Учитывая, что, начиная с версии 4.2.0, в настройках по умолчанию register_globals=off использования этих переменных не рекомендовано, даже если они определены. Лучший способ получения информации о загружаемых файлах — использовать массив $_FILES.
Для работы с загруженными файлами лучше всего использовать встроенные функции is_uploaded_file и move_uploaded_file, которые проверяют, был ли загружен файл, и помещают его в указанную папку соответственно. Более детальную информацию Вы можете найти на страницах руководства. Не стоит изобретать велосипед и работать самому с временными файлами, копировать их, удалять. Это уже сделано до Вас и для Вас.
Я все сделал правильно, но у меня что-то не работает. Может, у меня неправильно сконфигурирован сервер?
Если Вы «все сделали правильно», но Ваш код неработоспособен, или работает неправильно, не спешите отчаиваться. Возможно проблема не в Ваших руках, а в неверных настройках сервера. Вот список директив, которые имеют отношения к загрузке файлов:
В файле php.ini:
- Если Вы хотите узнать, где расположен Ваш php.ini, выполните <?php phpinfo();?>
- file_uploads — возможность запретить или разрешить загрузку файлов в целом. По умолчанию On.
- upload_max_filesize — максимальный размер файла, который может быть загружен. Если Вам необходимо работать с большими файлами, измените эту настройку. По умолчанию 2М. Не забудьте изменить post_max_size.
- post_max_size — общее ограничение сверху на размер данных, передаваемых в POST запросе. Если Вам необходимо работать с большими файлами, или передавать несколько файлов одновременно, измените эту настройку. Значение по умолчанию 8М.
- upload_tmp_dir — временная директория на сервере, в которую будут помещаться все загружаемые файлы. Проверьте, какие на нее выставлены права(если на данном этапе у Вас возникли сложности, смотрите пояснения в конце статьи). Такая директория должна существовать и у пользователя, под которым выполняется Apache, также должны быть права на запись в эту директорию. Если Вы работаете с включенным ограничением open_basedir — то временный каталог должен находиться внутри. Вам не нужно заботиться о ее чистке или об уникальности имен, PHP решает эту проблему за Вас.
В файле httpd.conf:
- Прежде всего, убедитесь, что Вы используете веб-сервер Apache 1.3 (последняя версия на момент написания статьи — 1.3.27). Если Вы используете Apache 2.0, Вам следует прочитать следующий отрывок из документации:Do not use Apache 2.0 and PHP in a production environment neither on Unix nor on Windows.
- Если Вы получили сообщение «POST Method Not Allowed», это означает, что надо искать что-то похожее на следующие директивы, и использовать ключевое слово Allow:<Limit POST >
Order allow,deny
Allow from all
</Limit> - Проблемы с загрузкой бинарных файлов — классический вопрос «почему бьются файлы при upload». Вот способ решения, предложенный Димой Бородином (http://php.spb.ru): В директории, где лежит скрипт, делаем файл .htaccess, в котором пишем: CharsetDisable On. В файл httpd.conf дописать строки:<Location />
CharsetRecodeMultipartForms Off
</Location>
Небольшие пояснения, к этому рецепту: вышеописанная проблема, когда загруженные на сервер архивы не распаковываются и картинки не отображаются, может возникать из-за того, что используется веб-сервер Russian Apache. Директива CharsetDisable отключает модуль charset-processing module, т.е. никакой перекодировки при скачивании файлов, находящихся в данной папке, происходить не будет. Директива CharsetRecodeMultipartForms выключает перекодировку данных, переданных методом POST с заголовком Content-Type: multipart/form-data. Т.е. двоичные данные, переданные с такой настройкой, будут оставлены в первоначальном виде, а все остальное наполнение сайта будет перекодировано согласно текущим настройкам сервера.
Но при этом могут возникнуть осложнения: будьте готовы к тому, что в некоторых случаях текстовые части запросов вам придется перекодировать самостоятельно. Вот что по этому поводу говорится в документации:
Используйте директиву CharsetRecodeMultipartForms, которая появилась в PL23, но при этом вам все-равно придется перекодировать вручную текстовые части запросов. Для этого можно использовать Russian Apache API, доступное в других модулях или Russian Apache Perl API, доступное из mod_perl.
Один из примеров определения кодировки вы можете найти тут: http://tony2001.phpclub.net/detect_charset/detect.phps
Самая свежая документация по Russian Apache находится на его официальном сайте: http://apache.lexa.ru/.
Не забывайте, что после любой смены конфигурации, Вам необходимо перезапустить Ваш веб-сервер.
Я хочу сделать вот такую штуку, но у меня никак не получается…
Загрузка нескольких файлов одновременно
На самом деле в этом нет никакой трудности. Этого можно достичь, используя, к примеру, вот такую форму:
<form action="file-upload.php" method="post" enctype="multipart/form-data"> Send these files:<br> <input name="userfile[]" type="file"><br> <input name="userfile[]" type="file"><br> <input type="submit" value="Send files"> </form>
И не забудьте увеличить post_max_size, если предполагается много файлов
Автоматическая загрузка файлов на сервер
Не стоит забывать, что файлы на диске пользователя — конфиденциальная информация, к которой ни JavaScript, ни уж тем более PHP не имеют ни малейшего отношения. До тех пор, пока пользователь сам не выбрал файл при помощи <input type=»file»> ни о какой работе с ним не может идти и речи. И не забывайте, что у данного поля ввода атрибут value защищен от записи.
Хранение файлов в базе данных mySQL
Если Вы собрались хранить загружаемы файлы в базе данных, Вам необходимо помнить следующие моменты:
- Необходимо использовать поле типа BLOB
- Перед тем, как класть в базу, не забыть применить к строке mysql_escape_string
- При отображении файла необходимо указывать заголовок content/type
Помните, что скрипт отображающий ваш HTML никак не связан со скриптом, который должен выводить изображение. Это должны быть два различные приложения.
Хранение картинок в базе не является хорошем стилем. Гораздо удобней хранить в базе лишь пути к файлам изображений.
Получение свойств изображения.
Если перед вами возникла задача проверить тип или размеры картинки перед загрузкой файла на сервер, вам потребуется функция getimagesize. В качестве аргумента она принимает имя файла на диске и возвращает массив, первые два элемента которого — ширина и высота соответственно, третий — тип изображения. В случае невозможности прочитать из указанного файла корректное изображение, функция возвращает ложь.
Загрузка файлов, имеющих русско-язычное название
При загрузке на сервер файлов, необходимо проверять их оригинальные имена на предмет наличия «нестандартных» символов (к примеру русских букв). В случае их присутствия необходимо произвести замену. Оригинальное имя файла можно найти в переменной $_FILES[‘userfile’][‘name’]. Про то, как перекодировать русскоязычную строку в транслит можно можно найти в архивах практически любого форума, посвященного php.
Отображения статуса загрузки или progress bar
Необходимо учитывать, что до полной загрузки файла, PHP не может оперировать ни размером файла, ни процентом его загрузки. Только когда файл уже находится на сервере PHP, то он получает возможность обращаться к информации. Если вам все-таки крайне необходимо реализовать такую возможность, воспользуйтесь Java-аплетом.
Проблемы с правами на сервере (upload_tmp_dir)
В *nix-подобных операционных системах каждой папке, файлу, ссылке выставлены соответствие права доступа. Они могут выглядеть как rwx-rw-r- или же как число 754.
Доступность файла или каталога зависят от идентификатора пользователя и идентификатора группы, в которую он входит. Режим в целом описывается в терминах трех последовательностей, по три буквы в каждой:
Владелец Группа Прочие (u) (g) (o) rwx rwx rwx
Здесь владелец, члены группы и все прочие пользователи обладают правами чтения файла, записи в него и его выполнения. Права — любая осмысленная комбинация следующих букв:
r - Право на чтение. (4) w - Право на запись. (2) x - Право на выполнение (поиск в каталоге). (1)
Для того, что бы загрузка файлов на сервер работала корректно, необходимо реализовать один из двух вариантов
- Установить владельцем каталога пользователя, с чьими привелегиями выполняется apache. Это можно узнать из файла httpd.conf или просмотрев список процессов на сервере. Права на каталог должны быть 700 (rwx——).
- Независимо от того, кто является владельцем каталога, установить права 777 (rwxrwxrwx).
<? $max_image_width = 380; $max_image_height = 600; $max_image_size = 64 * 1024; $valid_types = array("gif","jpg", "png", "jpeg"); if (isset($_FILES["userfile"])) { if (is_uploaded_file($_FILES['userfile']['tmp_name'])) { $filename = $_FILES['userfile']['tmp_name']; $ext = substr($_FILES['userfile']['name'], 1 + strrpos($_FILES['userfile']['name'], ".")); if (filesize($filename) > $max_image_size) { echo 'Error: File size > 64K.'; } elseif (!in_array($ext, $valid_types)) { echo 'Error: Invalid file type.'; } else { $size = GetImageSize($filename); if (($size) && ($size[0] < $max_image_width) && ($size[1] < $max_image_height)) { if (@move_uploaded_file($filename, "/www/htdocs/upload/")) { echo 'File successful uploaded.'; } else { echo 'Error: moving fie failed.'; } } else { echo 'Error: invalid image properties.'; } } } else { echo "Error: empty file."; } } else { echo ' <form enctype="multipart/form-data" method="post"> <input type="hidden" name="MAX_FILE_SIZE" value="64000"> Send this file: <input name="userfile" type="file"> <input type="submit" value="Send File"> </form>'; } ?>
Еще один прмер реализации, с использованием PEAR (подсказан kvn-ом). Оригинальный пакет находится по адресу:
http://pear.php.net/packages/HTTP_Upload
<html><body> <form action="<?php echo $HTTP_SERVER_VARS['PHP_SELF'];?>?submit=1" method="post" enctype="multipart/form-data"> Send these files:<br> <INPUT TYPE="hidden" name="MAX_FILE_SIZE" value="100000"> <input name="userfile" type="file"> <-<br> <input name="otherfile[]" type="file"><br> <input name="otherfile[]" type="file"><br> <input type="submit" value="Send files"> </form> </body></html> <?php error_reporting(E_ALL); if (!isset($submit)) { exit; } require 'HTTP/Upload.php'; echo '<pre>'; //print_r($HTTP_POST_FILES); $upload = new http_upload('es'); $file = $upload->getFiles('userfile'); if (PEAR::isError($file)) { die ($file->getMessage()); } if ($file->isValid()) { $file->setName('uniq'); $dest_dir = './wp-content/uploads/'; $dest_name = $file->moveTo($dest_dir); if (PEAR::isError($dest_name)) { die ($dest_name->getMessage()); } $real = $file->getProp('real'); echo "Uploaded $real as $dest_name in $dest_dirn"; } elseif ($file->isMissing()) { echo "No file selectedn"; } elseif ($file->isError()) { echo $file->errorMsg() . "n"; } print_r($file->getProp()); echo '</pre>'; ?>
Довольно часто возникает необходимость отправки на
сервер не только текстовых данных, но и отдельных пользовательских файлов, например, фотографий. В таком случае алгоритм действий также довольно прост
и понятен, однако несколько сложнее передачи простых текстовых данных. Код формы с полем для загрузки файла на сервер показан в примере №1.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Загрузка одиночных файлов</title> </head> <body> <form action="example_10_8.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="MAX_FILE_SIZE" value="3000000"> Загрузите аватарку (не более 3Мб):<br><br> <input type="file" name="userFile"><br><br> <button type="submit" name="submit" value="send">Отправить</button> </form> </body> </html>
<?php //Предполагается, что файл был успешно загружен $userFile = $_FILES['userFile']['name']; echo 'Имя вашего файла: '.$userFile.'<br>'; $userFileType = $_FILES['userFile']['type']; echo 'Тип вашего файла: '.$userFileType.'<br>'; $userFileSize = $_FILES['userFile']['size']; echo 'Размер вашего файла: '.$userFileSize.' байт'.'<br>'; $userFileTmp = $_FILES['userFile']['tmp_name']; echo 'Временное имя файла на сервере: '.$userFileTmp.'<br>'; $userFileError = $_FILES['userFile']['error']; echo 'Код ошибки: '.$userFileError.'<br>'; ?>
Пример №1. Код формы с полем для загрузки одиночных файлов на сервер
Скрытое поле должно предшествовать полю для выбора файла. Его атрибуты name = «MAX_FILE_SIZE» и
value = «30000» задают максимально допустимый размер загружаемого
файла. Рекомендуется всегда использовать данные параметры, т.к. это предотвращает ненужное ожидание пользователей при передаче огромных файлов только
для того, чтобы узнать, что файл слишком большой и его передача не состоялась. Конечно, обойти это ограничение на стороне браузера достаточно просто,
следовательно, не стоит полагаться на то, что все файлы большего размера будут блокированы при помощи этой возможности. Однако на сервере настройки
касательно максимального размера загружаемых файлов обойти практически невозможно.
Если в поле для отправки файлов задать атрибут accept, то в дополнение к ограничению на размер передаваемого файла
будет наложено ограничение и на возможные типы передаваемых файлов. Если файл не будет соответствовать фильтру, устанавливаемому данным атрибутом,
пользователь не увидит его в окне выбора файлов. Если атрибут не применяется, то в окне выбора файлов будут показываться все файлы, доступные для
просмотра.
Следует отметить, что для отправки файлов нужно обязательно указывать значение атрибута
enctype = «multipart/form-data», вместо значения
enctype = «application/x-www-form-urlencoded»
элемента «form», иначе загрузка файлов на сервер выполняться не будет.
После загрузки файла на сервер всю информацию о нем можно узнать из глобального массива $_FILES:
- $_FILES[‘userfile’][‘name’] – оригинальное имя файла на компьютере клиента;
-
$_FILES[‘userfile’][‘type’] – mime-тип файла, например,
«image/gif»; полагаться на его значение без проверки не стоит; - $_FILES[‘userfile’][‘size’] – размер в байтах принятого файла;
-
$_FILES[‘userfile’][‘tmp_name’] – временное имя, с которым принятый файл был сохранен на сервере
(точнее путь к файлу во временной папке, где ему присваивается временное имя); -
$_FILES[‘userfile’][‘error’] – код ошибки, которая может возникнуть при загрузке файла:
- UPLOAD_ERR_OK – значение: 0; файл был успешно загружен на сервер;
-
UPLOAD_ERR_INI_SIZE – значение: 1; размер принятого файла превысил
максимально допустимый размер, который установлен в директиве upload_max_filesize конфигурационного файла
php.ini; -
UPLOAD_ERR_FORM_SIZE – значение: 2; размер загружаемого файла
превысил значение «MAX_FILE_SIZE», указанное в HTML-форме; -
UPLOAD_ERR_PARTIAL – значение: 3; загружаемый файл был получен
только частично; - UPLOAD_ERR_NO_FILE – значение: 4; файл не был загружен;
- UPLOAD_ERR_NO_TMP_DIR – значение: 6; отсутствует временная папка;
- UPLOAD_ERR_CANT_WRITE – значение: 7; не удалось записать файл на диск;
-
UPLOAD_ERR_EXTENSION – значение: 8; какое-то из
PHP-расширений остановило загрузку файла, при этом PHP не предоставляет
способа определить, какое именно; в этом может помочь просмотр списка загруженных расширений из phpinfo().
Использование суперглобального массива $_FILES показано в примере №1.
Если нужно загрузить несколько файлов, то можно либо использовать в поле для отправки файлов атрибут multiple
(см. пример №2), либо не одно, а несколько соответствующих элементов «input».
При этом, если размер какого-либо из файлов превысит значение «MAX_FILE_SIZE», он загружен не будет. Однако это не
повлияет на загрузку остальных файлов, поэтому желательно сообщать о такой ситуации пользователю выводом соответствующего сообщения.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Загрузка нескольких файлов</title> </head> <body> <form action="example_9_10.php" method="POST" enctype="multipart/form-data"> <input type="hidden" name="MAX_FILE_SIZE" value="3000000"> Загрузите аватарки (не более 3Мб каждая):<br><br> <input type="file" name="userFile[]" multiple><br><br> <button type="submit" name="submit" value="send">Отправить</button> </form> </body> </html>
<?php //Будем считать, что как минимум один файл был загружен //Выводим информацию о первом из загруженных файлов $userFile = $_FILES['userFile']['name'][0]; echo 'Имя вашего файла: '.$userFile.'<br>'; $userFileType = $_FILES['userFile']['type'][0]; echo 'Тип вашего файла: '.$userFileType.'<br>'; $userFileSize = $_FILES['userFile']['size'][0]; echo 'Размер вашего файла: '.$userFileSize.' байт'.'<br>'; $userFileTmp = $_FILES['userFile']['tmp_name'][0]; echo 'Временное имя файла на сервере: '.$userFileTmp.'<br>'; $userFileError = $_FILES['userFile']['error'][0]; echo 'Код ошибки: '.$userFileError.'<br>'; ?>
Пример №2. Код формы с полем для загрузки нескольких файлов на сервер
При использовании атрибута multiple в качестве значения атрибута name
нужно использовать массив, иначе на сервере мы сможем получить данные только о последнем загруженном файле. После загрузки файлов на сервер доступ
к ним может быть получен, опять же, через суперглобальный массив $_FILES, с учетом того, что файлам в массиве
будут назначены числовые ключи согласно порядку их отправки (см. пример №2).
В случаях, когда необходимо по-разному ограничить размеры загружаемых файлов, следует выбирать второй вариант, используя несколько полей для
отправки файлов и указывая перед каждым из них скрытое поле с требуемым ограничением размера (см. пример. №3).
Кроме того, к файлам можно будет обращаться по их ключам, хотя можно поступить и предыдущим способом, просто объявив общий массив.
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Загрузка нескольких файлов</title> </head> <body> <form action="example_10_12.php" method="POST" enctype="multipart/form-data"> Загрузите фото (не более 1Мб): <input type="hidden" name="MAX_FILE_SIZE" value="1000000"> <input type="file" name="file_1"><br><br> Загрузите аватарку (не более 50Кб): <input type="hidden" name="MAX_FILE_SIZE" value="50000"> <input type="file" name="file_2"><br><br> <button type="submit" name="submit" value="send">Отправить</button> </form> </body> </html>
<?php //Будем считать, что оба файла были загружены //Выводим информацию о результатах загрузки файлов $fileName_1 = $_FILES['file_1']['name']; echo 'Имя вашего файла: '.$fileName_1.'<br>'; $fileError_1 = $_FILES['file_1']['error']; echo 'Код ошибки: '.$fileError_1.'<br>'.'<br>'; $fileName_2 = $_FILES['file_2']['name']; echo 'Имя вашего файла: '.$fileName_2.'<br>'; $fileError_2 = $_FILES['file_2']['error']; echo 'Код ошибки: '.$fileError_2.'<br>'.'<br>'; ?>
Пример №3. Код формы с несколькими полями загрузки файлов
В процессе загрузки файлов на сервер они помещаются во временную папку, которая задается в настройках конфигурационного файла
php.ini (подробно рассмотрим позже). Для того, чтобы переместить файл из временной папки в нужное место, нужно
использовать функцию move_uploaded_file(), которая проверяет, является ли файл загруженным на сервер по протоколу
HTTP POST, и в случае удачи перемещает загруженный файл в новое место, возвращая при этом
true (см. пример №4). Если же перемещение по каким-либо причинам невозможно, функция вернет
false (см. раздел «Расширения для работы с файловой системой» официального
справочника).
<?php
//Переместим файл, загруженный при помощи формы примера №1,
//в папку loaded_files
//Сохраним путь к файлу во временной папке в переменной
$userFileTmp = $_FILES['userFile']['tmp_name'];
//Сохраним в переменной исходное имя загруженного файла
$file_name = $_FILES['userFile']['name'];
//Путь построим от корня сайта / и заменим временное имя файла обратно на свое
$my_dir="/loaded_files/{$file_name}";
//Если файл будет перемещен, функция вернет true
if(move_uploaded_file($userFileTmp, $my_dir)){
echo "Файл корректен и был успешно перемещен.";
}else{
echo "Файл не был перемещен!";
}
?>
Пример №4. Перемещение загруженных файлов из временной папки
Если требуется переместить сразу несколько файлов, загруженных при помощи поля с атрибутом multiple
(см. примеры №2 и №3), можно воспользоваться, например, циклом
foreach, повторив процедуру перемещения для всех элементов массива.