Ошибка при загрузке файла на сервер php

Объяснение сообщений об ошибках

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; Отсутствует временная папка.

UPLOAD_ERR_CANT_WRITE

Значение: 7; Не удалось записать файл на диск.

UPLOAD_ERR_EXTENSION

Значение: 8; Модуль PHP остановил загрузку файла. PHP не
предоставляет способа определить, какой модуль остановил
загрузку файла; в этом может помочь просмотр списка загруженных
модулей с помощью phpinfo().

Viktor

9 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

14 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']);

}

?>

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

adam at gotlinux dot us

18 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"

);

?>

roland at REMOVE_ME dot mxchange dot org

5 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.'),
];
}
}
?>

svenr at selfhtml dot org

16 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

jille at quis dot cx

14 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).

Jeff Miner mrjminer AT gmail DOT com

13 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);

?>

sysadmin at cs dot fit dot edu

18 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

13 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.

Sohaib Essam

3 months ago

switch ($_FILES["image"]["error"]) {
case UPLOAD_ERR_PARTIAL:
exit('File only partially uploaded');
break;
case UPLOAD_ERR_NO_FILE:
exit('No file was uploaded');
break;
case UPLOAD_ERR_EXTENSION:
exit('File upload stopped by a PHP extension');
break;
case UPLOAD_ERR_FORM_SIZE:
exit('File exceeds MAX_FILE_SIZE in the HTML form');
break;
case UPLOAD_ERR_INI_SIZE:
exit('File exceeds upload_max_filesize in php.ini');
break;
case UPLOAD_ERR_NO_TMP_DIR:
exit('Temporary folder not found');
break;
case UPLOAD_ERR_CANT_WRITE:
exit('Failed to write file');
break;
default:
exit('Unknown upload error');
break;
}

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

16 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.

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

viseth10 at gmail dot com

6 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.

roger dot vermeir at nokia dot com

5 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

16 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

16 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());
}

I have a php file that uploads images like jpegs and png onto a folder called uploads that is stored on the apache server and in the same location as the php file.

I have checked the code of both the HTML and the PHP and both seem to be perfectly fine, however whenever I try to upload a file I always get an error message and the file doesn’t get uploaded.

It would be much appreciated if someone with more experience than me can look at my code and tell me why it is behaving in this manner.

Here is the HTML form:

<!--
To change this template, choose Tools | Templates
and open the template in the editor.
-->
<!DOCTYPE html>
<html>
<head>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Upload Your File</title>
</head>
<body>
    <?php
    // put your code here
    ?>

    <form enctype="multipart/form-data" method="post" action="fileHandler.php">
        Select File:
        <input name="uploaded_file" type="file"/><br/>
        <input type="submit" value="Upload"/>
    </form>
</body>
</html>

and here is the PHP file that is executed when the form is submitted:

<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 * PHP file that uploads files and handles any errors that may occur
 * when the file is being uploaded. Then places that file into the 
 * "uploads" directory. File cannot work is no "uploads" directory is created in the
 * same directory as the function. 
 */

$fileName = $_FILES["uploaded_file"]["name"];//the files name takes from the HTML form
$fileTmpLoc = $_FILES["uploaded_file"]["tmp_name"];//file in the PHP tmp folder
$fileType = $_FILES["uploaded_file"]["type"];//the type of file 
$fileSize = $_FILES["uploaded_file"]["size"];//file size in bytes
$fileErrorMsg = $FILES["uploaded_file"]["error"];//0 for false and 1 for true
$target_path = "uploads/" . basename( $_FILES["uploaded_file"]["name"]); 

echo "file name: $fileName </br> temp file location: $fileTmpLoc<br/> file type: $fileType<br/> file size: $fileSize<br/> file upload target: $target_path<br/> file error msg: $fileErrorMsg<br/>";

//START PHP Image Upload Error Handling---------------------------------------------------------------------------------------------------

    if(!$fileTmpLoc)//no file was chosen ie file = null
    {
        echo "ERROR: Please select a file before clicking submit button.";
        exit();
    }
    else
        if(!$fileSize > 16777215)//if file is > 16MB (Max size of MEDIUMBLOB)
        {
            echo "ERROR: Your file was larger than 16 Megabytes";

            unlink($fileTmpLoc);//remove the uploaded file from the PHP folder
            exit();
        }
        else
            if(!preg_match("/\.(gif|jpg|jpeg|png)$/i", $fileName))//this codition allows only the type of files listed to be uploaded
            {
                echo "ERROR: Your image was not .gif, .jpg, .jpeg or .png";
                unlink($fileTmpLoc);//remove the uploaded file from the PHP temp folder
                exit();
            }
            else
                if($fileErrorMsg == 1)//if file uploaded error key = 1 ie is true
                {
                    echo "ERROR: An error occured while processing the file. Please try again.";
                    exit();
                }


    //END PHP Image Upload Error Handling---------------------------------------------------------------------------------------------------------------------


    //Place it into your "uploads" folder using the move_uploaded_file() function
    $moveResult = move_uploaded_file($fileTmpLoc, $target_path);

    //Check to make sure the result is true before continuing
    if($moveResult != true)
    {
        echo "ERROR: File not uploaded. Please Try again.";
        unlink($fileTmpLoc);//remove the uploaded file from the PHP temp folder

    }
    else
    {
        //Display to the page so you see what is happening 
        echo "The file named <strong>$fileName</strong> uploaded successfully.<br/><br/>";
        echo "It is <strong>$fileSize</strong> bytes.<br/><br/>";
        echo "It is a <strong>$fileType</strong> type of file.<br/><br/>";
        echo "The Error Message output for this upload is: $fileErrorMsg";
    }
?>

В PHP-скрипте обработка загруженных через форму происходит через глобальный массив $_FILES, рассмотрим его содержимое:

1

Загрузка одного файла

Чтобы форма отправила файл, необходимо использовать только метод POST для отправки данных и добавить к тегу <form> атрибут enctype="multipart/form-data", который определяет способ кодирования данных формы при их отправке на сервер.

<form action="/index.php" method="post" enctype="multipart/form-data">
	<input type="file" name="file-1">
	<input type="submit" value="Отправить">
</form>

HTML

Код скрипта index.php:

<?php
print_r($_FILES['file-1']);

PHP

Результат:

Array(
	[name] => image.jpg
	[type] => image/jpeg
	[tmp_name] => /home/user/temp/phpjX2YXo
	[error] => 0
	[size] => 119303
)

Описание значений массива $_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'] Код ошибки, которая может возникнуть при загрузке файла.

2

Загрузка несколько файлов

Для загрузки сразу нескольких файлов к <input type="file"> нужно добавить атрибут multiple, а к имени поля – [].

<form action="/index.php" method="post" enctype="multipart/form-data">
	<input type="file" name="file-2[]" multiple>
	<input type="submit" value="Отправить">
</form>

HTML

Код скрипта index.php

<?php
print_r($_FILES['file-2']);

PHP

Результат:

Array(
	[name] => Array(
		[0] => image.jpg
		[1] => arhive.zip
	)
	[type] => Array(
		[0] => image/jpeg
		[1] => application/zip
	)
	[tmp_name] => Array(
		[0] => /home/user/temp/phpK3h32F
		[1] => /home/user/temp/phpBrGxus
	)
	[error] => Array(
		[0] => 0
		[1] => 0
	)
	[size] => Array(
		[0] => 119303
		[1] => 6792
	)
)

Как видно, структура массива разделена по свойствам, а не по файлам. Для удобства работы с циклом foreach массив $_FILES можно преобразовать:

<?php
$files = array();
foreach($_FILES['file-2'] as $k => $l) {
	foreach($l as $i => $v) {
		$files[$i][$k] = $v;
	}
}		
$_FILES['file-2'] = $files;

print_r($_FILES);

PHP

Результат:

Array(
	[0] => Array(
		[name] => image.jpg
		[type] => image/jpeg
		[tmp_name] => /home/user/temp/phpKgSQbo
		[error] => 0
		[size] => 119303
	)
	[1] => Array(
		[name] => arhive.zip
		[type] => application/zip
		[tmp_name] => /home/user/temp/phpVht8LS
		[error] => 0
		[size] => 6792
	)
)

3

Максимальный размер загружаемого файла

Размер загружаемого файла можно ограничить, добавив в форму скрытое поле с максимальным размером файла <input type="hidden" name="MAX_FILE_SIZE" value="2097152">:

<form action="/index.php" method="post" enctype="multipart/form-data">
	<input type="hidden" name="MAX_FILE_SIZE" value="2097152"> 
	<input type="file" name="file-1">
	<input type="submit" value="Отправить">
</form>

HTML

В случае превышения размера файла в переменной $_FILES['file-1']['error'] будет ошибка с кодом «2».

4

Коды ошибок загрузки файлов

В случаи, если при загрузке файла произошла ошибка, в переменной $_FILES['file']['error'] будет содержатся её код. Возможны следующие значения:

Код Константа Описание
0 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-расширение остановило загрузку файла.

5

Настройки PHP

Обычно настройки загрузки файлов на хостинге вполне нормальные и не вызывают проблем, но есть исключения. Если не загружаются большие файлы, то скорее всего установлен лимит на размер загружаемого файла, ограничено время загрузки файла или ограничено количество одновременных загрузок.

Посмотреть установленные значения можно с помощью функции phpinfo(), в разделе «Core».

Раздел «Core» в phpinfo

В php.ini:

; Разрешение на загрузку файлов
file_uploads = On

; Максимальное время выполнения скрипта в секундах
max_execution_time = 60
 
; Максимальное потребление памяти одним скриптом
memory_limit = 64M
 
; Максимально допустимый размер данных отправляемых методом POST
post_max_size = 50M

; Папка для хранения файлов во время загрузки
upload_tmp_dir = home/user/temp
 
; Максимальный размер загружаемого файла
upload_max_filesize = 5M
 
; Максимально разрешённое количество одновременно загружаемых файлов
max_file_uploads = 10

В .htaccess:

# Разрешение на загрузку файлов
php_value file_uploads On

# Максимальное время выполнения скрипта в секундах
php_value max_execution_time 60
 
# Максимальное потребление памяти одним скриптом
php_value memory_limit 64M
 
# Максимально допустимый размер данных отправляемых методом POST
php_value post_max_size 50M

# Папка для хранения файлов во время загрузки
php_value upload_tmp_dir home/user/temp
 
# Максимальный размер загружаемого файла
php_value upload_max_filesize 5M
 
# Максимально разрешённое количество одновременно загружаемых файлов
php_value max_file_uploads 10

htaccess

В PHP скрипте:

<?php

// Разрешение на загрузку файлов
ini_set('file_uploads', 'On');

// Максимальное время выполнения скрипта в секундах
ini_set('max_execution_time', '60');
 
// Максимальное потребление памяти одним скриптом
ini_set('memory_limit', '64M');
 
// Максимально допустимый размер данных отправляемых методом POST
ini_set('post_max_size', '50M');

// Папка для хранения файлов во время загрузки
ini_set('upload_tmp_dir', 'home/user/temp');
 
// Максимальный размер загружаемого файла
ini_set('upload_max_filesize', '5M');
 
// Максимально разрешённое количество одновременно загружаемых файлов
ini_set('max_file_uploads', '10');

PHP

Другие публикации

Загрузка файлов через AJAX с помощью jQuery Form Plugin

Пример загрузки изображений через AJAX с помощью плагина jQuery Form Plugin.

Загрузка файлов через jQuery AJAX

В преведущей статье был приведен пример отправки файлов через AJAX с помощью плагина «jQuery Form Plugin». Но файлы…

Загрузка изображений с превью AJAX + PHP + MySQL

В данной статье представлена упрощенная реализация загрузки изображений с превью через AJAX с сохранением в базу данных…

Запрет выполнения PHP скриптов в директории

Если нужно запретить выполнение скриптов php в директории, например в uploads, нужно поместить туда файл .htaccess со…

Примеры отправки AJAX JQuery

AJAX позволяет отправить и получить данные без перезагрузки страницы. Например, делать проверку форм, подгружать контент и т.д. А функции JQuery значительно упрощают работу.

Примеры использования cURL в PHP

cURL PHP – это библиотека предназначенная для получения и передачи данных через такие протоколы, как HTTP, FTP, HTTPS….

Okay, so I set up an upload engine for a website so that an authenticated user can upload a audio file (a key) for a song in the library, but I come across this strange problem when I try to upload any file over 5MB.

I set my php.ini max filesize to 50MB by the way

Everything uploads properly, but there is no data associated with the file on the other end.

HTML CODE:

<form action="keyUpload.php?id=<?php echo $id;?>" method="post" enctype="multipart/form-data">
<p style="color:#fff;font-size:30px;font-family:Times">
Add a new Key:<br/><input name="uploaded" type="file" id="file"><br />
<input type="text" name="kname" id="kname" value placeholder="Key Name (Ex. Demo, A#, etc.)" style="width:300px;"><br/>
<button class="button">Upload File</button><br/>
<span style="font-size:12px;">*Max Filesize is 50 MB*</span>
</p>
</form>

PHP CODE:

<?php 
$id=$_GET["id"];
$name=$_POST["kname"];

$name = str_replace(" ","%20",$name);

$allowed_filetypes = array('.mp3','.m4a','.wav','.wma');

$filename = $_FILES['uploaded']['name'];
$ext = substr($filename, strpos($filename,'.'), strlen($filename)-1);

Both $filename and $ext are empty variables when I upload a file larger than 5 MB. In all other cases, this engine works perfectly.

When echoed, simply nothing happens, so obviously the engine will not save the file if it doesn’t exist. What’s going on?

var_dump:

array(0) { }

Thanks for all your help!

Загрузка файлов на сервер

В прошлом уроке мы научились работать с файлами в PHP, а именно – читать и писать данные в файлы. Теперь давайте рассмотрим возможность языка PHP, позволяющую загружать пользователю файлы на сервер.

Для начала давайте обговорим, как будет выглядеть наше мини-приложение. Пусть у нас будет форма для загрузки файлов: upload.php. Этот же файл будет содержать логику по обработке загружаемых пользователем файлов. И ещё давайте создадим папку uploads, в которую будем складывать все загружаемые файлы.

Давайте для начала напишем саму форму для загрузки файла. Она ничем не отличается от обычной формы для POST-запроса. Единственное отличие – появляется input со специальным типом file. У него также как и у текстового input’а есть атрибут name. Простейшая форма для загрузки файла будет выглядеть следующим образом. Содержимое файла upload.php:

<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<form action="/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>

Для того, чтобы начать работать с файлом на стороне PHP, нужно познакомиться с ещё одним суперглобальным массивом в PHP — $_FILES. Так как мы указали в input атрибуту name значение attachment, то и узнать информацию о загружаемом нами файле можно получить по соответствующему ключу — $_FILES[‘attachment’].

Давайте разместим PHP-код для обработки загружаемого файла в этом же файле. Для начала просто посмотрим что у нас там вообще есть с помощью var_dump.

<?php
if (!empty($_FILES)) {
    var_dump($_FILES);
}
?>
<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<form action="/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>

Откроем в браузере нашу форму http://myproject.loc/upload.php, и выберем какой-нибудь файл для загрузки. Я для этого выбрал картинку, валяющуюся на рабочем столе.
выбор файла для загрузки

После нажатия на кнопку «Отправить» мы получим содержимое массива $_FILES.
Суперглобальный массив $_FILES

Значение $_FILES[‘attachment’] представляет собой массив с пятью ключами. Давайте рассмотрим каждый из элементов этого массива более подробно.

  • name – имя файла, переданное из браузера;
  • type – тип файла, в моём случае это image/png;
  • tmp_name – путь до временного файла, который загрузился на сервер, но если с ним до конца запроса ничего не сделать, то он удалится;
  • error – код ошибки при загрузке файла, если 0 – то ошибки нет. Изучите возможные коды ошибок вот тут;
  • size – размер загруженного файла в байтах.

Как мы уже сказали, пока что на сервере создан временный файл. Чтобы его сохранить нужно вызвать специальную функцию, которая переместит его из временной папки в нужную нам папку (в нашем случае это папка uploads). Эта функция — move_uploaded_file(). Первым аргументом она принимает путь до временного файла (в нашем случае — $_FILES[‘attachment’][‘tmp_name’]), а вторым аргументом – путь, по которому нужно его сохранить. Функция вернёт true, если всё ок, и false, если что-то пошло не так.

ВНИМАНИЕ! Для перемещения временного файла в нужную вам папку стоит всегда использовать функцию move_uploaded_file(). Она предварительно проверяет, что указанный файл действительно является временным загруженным файлом, а не чем-то ещё. Другие функции для копирования файлов не подойдут, так как они эту проверку не выполняют, а это небезопасно. Кому интересно – можете подробнее прочитать тут.

В простейшем виде скрипт для загрузки файла на сервер будет выглядеть следующим образом.

<?php
if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];

    // собираем путь до нового файла - папка uploads в текущей директории
    // в качестве имени оставляем исходное файла имя во время загрузки в браузере
    $srcFileName = $file['name'];
    $newFilePath = __DIR__ . '/uploads/' . $srcFileName;

    if (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/uploads/' . $srcFileName;
    }
}
?>
<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<?php if (!empty($error)): ?>
    <?= $error ?>
<?php elseif (!empty($result)): ?>
    <?= $result ?>
<?php endif; ?>
<br>
<form action="/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>

Если сейчас выбрать файл и нажать на кнопку “Отправить”, то скрипт вернёт нам адрес загруженного файла.
Результат загрузки файла через PHP

Мы можем открыть этот адрес в новой вкладке, и убедиться, что действительно файл доступен по этому адресу. Ну и если посмотрим в папку uploads, то тоже увидим, что наш файлик теперь там валяется.

Этот скрипт ещё очень сырой, давайте его доработаем.

Проверка на существующий файл с таким же именем

Первое, что приходит на ум – убедиться, что файл с таким именем не загружался ранее. Иначе мы рискуем перезатереть что-нибудь важное. Давайте проверим существование такого файла с помощью функции file_exists().

<?php
if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];

    $srcFileName = $file['name'];
    $newFilePath = __DIR__ . '/uploads/' . $srcFileName;

    if (file_exists($newFilePath)) {
        $error = 'Файл с таким именем уже существует';
    } elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/uploads/' . $srcFileName;
    }
}
?>
...

Обработка ошибок при загрузке файлов

Теперь вспомним об элементе массива по ключу error. Как мы помним, при отсутствии ошибок там будет 0. Во всех остальных случаях стоит уведомить пользователя об ошибках при загрузке файла. Если мы прочитаем вот эту страничку документации, то увидим, что ошибки на самом деле могут быть самыми разными.

Хороший код должен обрабатывать каждую из этих ошибок и выдавать соответствующую информацию пользователю. Мы же в учебном примере ограничимся только проверкой на 0, будет большим плюсом, если вы самостоятельно напишите обработку всех этих ошибок в своём коде. Итак, результат.

<?php
if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];

    $srcFileName = $file['name'];
    $newFilePath = __DIR__ . '/uploads/' . $srcFileName;

    if ($file['error'] !== UPLOAD_ERR_OK) {
        $error = 'Ошибка при загрузке файла.';
    } elseif (file_exists($newFilePath)) {
        $error = 'Файл с таким именем уже существует';
    } elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/uploads/' . $srcFileName;
    }
}
?>
...

Проверяем расширение загружаемого файла

Ещё необходимо проверить то, что у загружаемого файла корректное расширение. Например, если мы хотим чтобы через форму загружали только картинки, то допустимыми расширениями для нас будут .jpg, .gif, .png.

Если этого не предусмотреть – то через форму загрузки можно будет загрузить какой-нибудь вредоносный скрипт. Представьте, что кто-то загрузил на сервер .php-скрипт, который удаляет все файлы в текущей директории, а затем просто запустил его, зайдя по адресу http://myproject.loc/uploads/very_bad_script.php. И это еще не самое страшное, что могут сделать злобные хакеры. Поэтому нужно всегда контролировать то, что пользователи загружают на сервер.

Получить расширение файла можно при помощи функции pathinfo(). Первым аргументом передаётся путь до файла, вторым – константа PATHINFO_EXTENSION.

$extension = pathinfo($srcFileName, PATHINFO_EXTENSION);

В переменной $extension после это будет строка c расширением загруженного файла, например, png.
Нам остаётся только проверить, что расширение загружаемого файла находится в списке разрешенных. Давайте создадим массив со списком таких расширений и проверим наличие расширения загружаемого файла в списке разрешенных.

$allowedExtensions = ['jpg', 'png', 'gif'];
$extension = pathinfo($srcFileName, PATHINFO_EXTENSION);
if (!in_array($extension, $allowedExtensions)) {
    $error = 'Загрузка файлов с таким расширением запрещена!';
}

Теперь, если вы попробуете загрузить файл с каким-то другим расширением, то скрипт на нас ругнётся.
Ошибка при плохом расширении

Результат

В ходе данного урока получили скрипт следующего содержания.

<?php
if (!empty($_FILES['attachment'])) {
    $file = $_FILES['attachment'];

    $srcFileName = $file['name'];
    $newFilePath = __DIR__ . '/uploads/' . $srcFileName;

    $allowedExtensions = ['jpg', 'png', 'gif'];
    $extension = pathinfo($srcFileName, PATHINFO_EXTENSION);
    if (!in_array($extension, $allowedExtensions)) {
        $error = 'Загрузка файлов с таким расширением запрещена!';
    } elseif ($file['error'] !== UPLOAD_ERR_OK) {
        $error = 'Ошибка при загрузке файла.';
    } elseif (file_exists($newFilePath)) {
        $error = 'Файл с таким именем уже существует';
    } elseif (!move_uploaded_file($file['tmp_name'], $newFilePath)) {
        $error = 'Ошибка при загрузке файла';
    } else {
        $result = 'http://myproject.loc/uploads/' . $srcFileName;
    }
}
?>
<html>
<head>
    <title>Загрузка файла</title>
</head>
<body>
<?php if (!empty($error)): ?>
    <?= $error ?>
<?php elseif (!empty($result)): ?>
    <?= $result ?>
<?php endif; ?>
<br>
<form action="/upload.php" method="post" enctype="multipart/form-data">
    <input type="file" name="attachment">
    <input type="submit">
</form>
</body>
</html>

Есть ещё несколько проверок, которые было бы неплохо провести, прежде чем позволить загрузить файл на сервер. О них вы узнаете в домашнем задании.

loader

Понравилась статья? Поделить с друзьями:
  • Ошибка при загрузке приложения 0xc0000906
  • Ошибка при загрузке файла на гугл диск
  • Ошибка при загрузке сообщения outlook
  • Ошибка при загрузке приложения 0xc0000142
  • Ошибка при загрузке файла на госуслугах