Php скачивание нескольких файлов. Загрузка файлов на сервер с помощью PHP

Multiple files can be uploaded using different name for input .

It is also possible to upload multiple files simultaneously and have the information organized automatically in arrays for you. To do so, you need to use the same array submission syntax in the HTML form as you do with multiple selects and checkboxes:

Send these files:


Warning

As of PHP 5.2.12, the max_file_uploads configuration setting acts as a limit on the number of files that can be uploaded in one request. You will need to ensure that your form does not try to upload more files in one request than this limit.

14 years ago

When uploading multiple files, the $_FILES variable is created in the form:

Array
=> Array
=> foo.txt
=> bar.txt
)

=> Array
=> text/plain
=> text/plain
)

=> Array
=> /tmp/phpYzdqkD
=> /tmp/phpeEwEWG
)

=> Array
=> 0
=> 0
)

=> Array
=> 123
=> 456
)

I found it made for a little cleaner code if I had the uploaded files array in the form

Array
=> Array
=> foo.txt
=> text/plain
=> /tmp/phpYzdqkD
=> 0
=> 123
)

=> Array
=> bar.txt
=> text/plain
=> /tmp/phpeEwEWG
=> 0
=> 456
)

I wrote a quick function that would convert the $_FILES array to the cleaner (IMHO) array.

Function reArrayFiles (& $file_post ) {

$file_ary = array();
$file_count = count ($file_post [ "name" ]);
$file_keys = array_keys ($file_post );

For ($i = 0 ; $i < $file_count ; $i ++) {
foreach ($file_keys as $key ) {
$file_ary [ $i ][ $key ] = $file_post [ $key ][ $i ];
}
}

Return $file_ary ;
}

?>

Now I can do the following:

If ($_FILES [ "upload" ]) {
$file_ary = reArrayFiles ($_FILES [ "ufile" ]);

Foreach ($file_ary as $file ) {
print "File Name: " . $file [ "name" ];
print "File Type: " . $file [ "type" ];
print "File Size: " . $file [ "size" ];
}
}

?>

5 years ago

This is also needed for elements.

So, if you have an input element like this:

This should be written as

else you"ll only be able to get one of the files.

9 years ago

Here is a function to fix the indices of a multi-dimensional for easier parsing when dealing with file uploads. It takes a single $_FILES field array as a parameter and separates each individual uploaded file by numeric key. This allows for iterating like:

fixFilesArray ($_FILES [ "array_of_files" ]);
foreach ($_FILES [ "array_of_files" ] as $position => $file ) {
// should output array with indices name, type, tmp_name, error, size
var_dump ($file );
}
?>

Here"s the code:

/**
* Fixes the odd indexing of multiple file uploads from the format:
*
* $_FILES["field"]["key"]["index"]
*
* To the more standard and appropriate:
*
* $_FILES["field"]["index"]["key"]
*
* @param array $files
* @author Corey Ballou
* @link http://www.jqueryin.com
*/
function fixFilesArray (& $files )
{
$names = array("name" => 1 , "type" => 1 , "tmp_name" => 1 , "error" => 1 , "size" => 1 );

Foreach ($files as $key => $part ) {
// only deal with valid keys and multiple files
$key = (string) $key ;
if (isset($names [ $key ]) && is_array ($part )) {
foreach ($part as $position => $value ) {
$files [ $position ][ $key ] = $value ;
}
// remove old key reference
unset($files [ $key ]);
}
}
}
?>

3 years ago

This is a very simple example:





Document







echo "

"
;
$img = $_FILES [ "img" ];

if(!empty($img ))
{
$img_desc = reArrayFiles ($img );
print_r ($img_desc );

Foreach($img_desc as $val )
{
$newname = date ("YmdHis" , time ()). mt_rand (). ".jpg" ;
move_uploaded_file ($val [ "tmp_name" ], "./uploads/" . $newname );
}
}

function reArrayFiles ($file )
{
$file_ary = array();
$file_count = count ($file [ "name" ]);
$file_key = array_keys ($file );

For($i = 0 ; $i < $file_count ; $i ++)
{
foreach($file_key as $val )
{
$file_ary [ $i ][ $val ] = $file [ $val ][ $i ];
}
}
return $file_ary ;
}

2 years ago

Once I had to do a maintenance in a huge ERP that had several multiple upload inputs inside an array. Just like this:







The $_FILES array is created like this:

Array
=> Array
=> Array
=> teste.c
=> teste
)

=> Array
=> text/x-csrc
=> application/octet-stream
)

=> Array
=> /opt/lampp/temp/phpuf3KNj
=> /opt/lampp/temp/php0yPZap
)

=> Array
=> 0
=> 0
)

=> Array
=> 1960
=> 8661
)

=> Array
=> Array
=> jefrey.html
=> notas.txt
)

=> Array
=> text/html
=> text/plain
)

=> Array
=> /opt/lampp/temp/php87nfyu
=> /opt/lampp/temp/phpUBlvVz
)

=> Array
=> 0
=> 0
)

=> Array
=> 583
=> 191
)

I"ve managed to re-arrange this array like this:

Array
=> Array
=> Array
=> teste.c
=> text/x-csrc
=> /opt/lampp/temp/phpuf3KNj
=> 0
=> 1960
)

=> Array
=> teste
=> application/octet-stream
=> /opt/lampp/temp/php0yPZap
=> 0
=> 8661
)

=> Array
=> Array
=> jefrey.html
=> text/html
=> /opt/lampp/temp/php87nfyu
=> 0
=> 583
)

=> Array
=> notas.txt
=> text/plain
=> /opt/lampp/temp/phpUBlvVz
=> 0
=> 191
)

Here"s my snippet:
function reArrayFilesMultiple (& $files ) {
$uploads = array();
foreach($_FILES as $key0 => $FILES ) {
foreach($FILES as $key => $value ) {
foreach($value as $key2 => $value2 ) {
$uploads [ $key0 ][ $key2 ][ $key ] = $value2 ;
}
}
}
$files = $uploads ;
return $uploads ; // prevent misuse issue
}
?>

3 years ago

This is just a modification of the code which is the top note by "phpuser" here. His/her version requires that the $file_post array passed in to the function was created by a form submitted with the multiple attribute set. With multiple set in the html input tag, $_FILES["fileInputName"]["name"] is an array no matter if only one file is sent or multiple. But when is used without the multiple attribute then $_FILES["fileInputName"]["name"] is not an array, it contains the the string with the filename. To use this neat function with or without multiple set and to get back an array which you can "foreach" over in either case, use this modification:

function reArrayFiles(&$file_post)
{
$file_ary = array();
$multiple = is_array($file_post["name"]);

$file_count = $multiple ? count($file_post["name"]) : 1;
$file_keys = array_keys($file_post);

For ($i=0; $i<$file_count; $i++)
{
foreach ($file_keys as $key)
{
$file_ary[$i][$key] = $multiple ? $file_post[$key][$i] : $file_post[$key];
}
}

Return $file_ary;
}

3 years ago

Recursive solution for complex situations (supports any nested arrays including indexed arrays)

function getFixedFilesArray() {
$walker = function ($arr, $fileInfokey, callable $walker) {
$ret = array();
foreach ($arr as $k => $v) {
if (is_array($v)) {
$ret[$k] = $walker($v, $fileInfokey, $walker);
} else {
$ret[$k][$fileInfokey] = $v;
}
}
return $ret;
};

$files = array();
foreach ($_FILES as $name => $values) {
// init for array_merge
if (!isset($files[$name])) {
$files[$name] = array();
}
if (!is_array($values["error"])) {
// normal syntax
$files[$name] = $values;
} else {
// html array feature
foreach ($values as $fileInfoKey => $subArray) {
$files[$name] = array_replace_recursive($files[$name], $walker($subArray, $fileInfoKey, $walker));
}
}
}

Return $files;
}

10 years ago

If you try and upload files with multi-dimensional names like this:


You will get an unexpected format like this:

array(
"submission" => array
"name" => array("screenshot" => "monster_wallpaper.jpg" ),
"type" => array("screenshot" => "image/jpeg" ),
"tmp_name" => array("screenshot" => "/tmp/php48lX2Y" ),
"error" => array("screenshot" => 0 ),
"size" => array("screenshot" => 223262 ),
),
....
?>

You can use the following function to re-format the array recursively in the usual format:

function format_files_array ($files , $name = null , & $new = false , $path = false ){
$names = array("name" => "name" , "type" => "type" , "tmp_name" => "tmp_name" , "error" => "error" , "size" => "size" );

Foreach($files as $key => & $part )
{
$key = (string) $key ;
if(in_array ($key , $names ))
$name = $key ;
if(! in_array ($key , $names ))
$path = $key ;
if(is_array ($part ))
$part = format_files_array ($part , $name , $new , $path );
elseif(! is_array ($part ))
{
$current =& $new ;
foreach($path as $p )
$current =& $current [ $p ];
$current [ $name ] = $part ;
unset($path );
$name = null ;
}
}

Return $new ;
}
?>

Приложение для загрузки файлов на сервер представляет собой HTML-форму (upload.html) и скрипт upload.php для ее обработки.

Замечание: Вы можете загрузить промышленную версию системы загрузки файлов на сервер из раздела . Система позволит вам не только загрузить файл на сервер, но и изменить его размер, фон и др.

Код формы (upload.html)

Форма для загрузки файлов



Код скрипта обработки формы (upload.php)

Результат загрузки файла 1024 * 3 * 1024 ) { echo (); exit; } // Проверяем загружен ли файл if(is_uploaded_file ($_FILES [ "filename" ][ "tmp_name" ])) { // Если файл загружен успешно, перемещаем его // из временной директории в конечную move_uploaded_file ($_FILES [ "filename" ][ "tmp_name" ], "/path/to/file/" . $_FILES [ "filename" ][ "name" ]); } else { echo("Ошибка загрузки файла" ); } ?>

Атрибут entype формы определяет вид кодировки, которую браузер применяет к параметрам формы. Для того чтобы отправка файлов на сервер действовала, атрибуту entype необходимо присвоить значение multipart/form-data. По умолчанию этот атрибут имеет значение application/x-www-form-urlencoded.

Элемент ввода этой формы должен иметь тип file.

После того, как получен HTTP-запрос, содержимое загруженного файла записывается во временный файл, который создается в каталоге сервера, заданном по умолчанию для временных файлов, если другой каталог не задан в файле php.ini (директива upload_tmp_dir).

Характеристики загруженного файла доступны через двумерный массив $_FILES.

Cкрипт upload.php загружает файл на сервер и копирует его в каталог /path/to/file/.

В некоторых случаях требуется ограничить размер файла, который может быть загружен на сервер. К примеру, чтобы разрешить загрузку на сервер только файлов с размером не более 3 Мбайт, в приведенном скрипте содержится код:

1024 * 3 * 1024 ) { echo("Размер файла превышает три мегабайта" ); exit; } ... ?>

Максимальный размер загружаемого файла можно также задать при помощи директивы upload_max_filesize, значение которой по умолчанию равно 2 Мбайт:

upload_max_filesize ) .. ?>

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

Для этого нам понадобится html форма с полем ввода типа . Кроме того, для передачи файлов на сервер необходимо форме установить тип multipart . Для этого в качестве параметра enctype указывается значение multipart/form-data .

После того, как на html страничке мы разместим форму с полем в окне браузера отобразится поле с возможностью выбрать файл на локальном компьютере.

После того, как пользователь выберет нужный файл и нажмет кнопку «Загрузить» форма передаст данные php скрипту на сервер, который указан в action формы. Если action формы пустой, то данные будут переданы тому же файлу, на котором находится форма. Вся информация о загружаемом файле помещается в массив $ _FILES . Нам лишь остается извлечь эту информацию и переместить файл в необходимое нам место.

Прежде, чем приступить к написанию скрипта обработки multipart-формы , нужно отредактировать файл конфигурации php.ini , чтобы разрешить загрузку файлов на сервер.

Конфигурационный файл PHP php.ini имеет три параметра, связанные с загрузкой файлов на сервер:

  • file_uploads = On - разрешает загрузку файлов на сервер по протоколу HTTP;
  • upoad_tmp_dir = /tmp - устанавливает каталог для временного хранения загруженных файлов;
  • upload_max_filesize = 2M - устанавливает максимальный объем загружаемых файлов.

Итак, создайте новый файл с именем upload.php и скопируйте в него следующий код.

Если внимательно посмотреть на форму, то Вы увидите скрытое поле

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

После того как пользователь выбрал файл и нажал на кнопку «Загрузить», вся информация о файле, как упоминалось ранее, помещается в массив $ _FILES, а сам файл помещается во временный каталог на сервере, который указан в в php.ini.

Так как поле file называлось name="uploadFile" , то массив $ _FILES будет содержать ассоциативный массив с ключом "uploadFile" .

  • $_FILES[" uploadFile "]["name"] - имя файла до его отправки на сервер, например, pict.gif;
  • $_FILES[" uploadFile "]["size"] - размер принятого файла в байтах;
  • $_FILES[" uploadFile "]["type"] - MIME-тип принятого файла (если браузер смог его определить), например: image/gif, image/png, image/jpeg, text/html;
  • $_FILES[" uploadFile "]["tmp_name"] - содержит имя файла во временном каталоге, например: /tmp/phpV3b3qY;
  • $_FILES[" uploadFile "]["error"] - Код ошибки, которая может возникнуть при загрузке файла.

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

Итак, с алгоритмом разобрались! Теперь давайте взглянем на код.

Первым делом мы проверяем была ли нажата кнопка submit.

If(isset($_POST["upload"])) { }

If(is_uploaded_file($_FILES["uploadFile"]["tmp_name"])) { Выполняем действие над файлом } else { echo "Файл не загружен"; }

Если файл был загружен через HTTP POST, то далее мы его перемещаем из временного каталога в нужный нам каталог. Это делается при помощи функции move_uploaded_file, которая принимает два параметра: имя файла для загрузки и путь куда будет перемещен файл. В случае успешного перемещения файла, данная функция возвратит true, в противном случае -false.

If(move_uploaded_file($_FILES["uploadFile"]["tmp_name"], $uploadedFile)) { echo Файл загружен; } else { echo Во время загрузки файла произошла ошибка; }

В нашем случае в качестве имени файла выступает имя временного файла на сервере - $_FILES["uploadFile"]["tmp_name"], а в качестве каталога, куда будет перемещен файл - переменная $uploadedFile, которая было объявлена выше в скрипте и содержит новое место хранения файла.

$folder = "path/to/folder/"; $uploadedFile = $folder. basename($_FILES["uploadFile"]["name"]);

Из своего опыта могу сказать, что хранить оригинальное название файла на сервере не стоит, поэтому его можно переименовать. Для этого сгенерируем случайное название для нашего файла и функция move_uploaded_file() переместит и переименует наш файл:

// Получаем расширение файла $file_ext = strtolower(strrchr($_FILES["uploadFile"]["name"],".")); // Генерируем случайное число $file_name = uniqid(rand(10000,99999)); // Формируем путь на сервере $uploadedFile = $folder.$file_name.$file_ext;

Ну и напоследок приведу список возможных ошибок, которые возникают во время загрузки файлов на сервер. Напоминаю, что код ошибки хранится в переменной $_FILES[" uploadFile "]["error"]:

  • 0- Ошибок не возникало, файл был успешно загружен на сервер.
  • 1- Размер принятого файла превысил максимально допустимый размер, который задан директивой upload_max_filesize конфигурационного файла php.ini..
  • 2- Размер загружаемого файла превысил значение MAX_FILE_SIZE , указанное в HTML-форме.
  • 3- Загружаемый файл был получен только частично.
  • 4- Файл не был загружен.
  • 6- Нет временную папку.
  • 7- Сбой при записи файлов на диск.

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

При помощи нашего скритпа злоумышленник сможет загружать произвольные файлы на сервер, к примеру, он сможет закачать на сервер php-скрипт, который рекурсивно сможет удалить все ваши файлы на сервере или PHP-shell, так что если вы пишите свой загрузчик файлов, то к этому делу надо подойти серьезно, ничего не упустив.

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

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

HTML форма отправки файла

Самая простая форма загрузки файла:





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

Параметр entype получает в этой форме значение multipart/form-data, что определяет, что в данной форме будет выполнена отправка бинарных данных, т.е. файла. Если это значение не указать, то по умолчанию форма будет выполняться как отправка текстовой информации.

Параметр MAX_FILE_SIZE , указанный в форме определяет максимальный размер файла, заданный в байтах. По умолчанию, этот размер определяется настройками сервера.

Для указания загружаемого файла тег должен содержать тип "file", а так же для дальнейшей работы PHP-скрипта следует указать значение "name".

Отправка данных формы выполняется тегом с типом "submit". Он отображается обычной кнопкой.

PHP код сохранения файла

Задача этого обработчика, получив данные формы, проверить ее на возможные ошибки, переместить полученный сервером временный файл в нужное место с заданным именем. Здесь же могут выполнять еще различные необходимые операции – запись информации в БД, создание уменьшенных копий изображений, сохранение изображений с добавлением авторских прав и многое другое.

В принимающем коде, данные о файле содержатся суперглобальном массиве $_FILES. Соответственно, просмотреть сведения об отправленном из формы файле, можно в $_FILES["my_file"]. Такой массив содержит следующую информацию:

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

Копирование выполняется функцией copy() , параметрами которой служит имя исходного файла (для этого случая имя временного файла - $_FILES["my_file"]["tmp_name"]) и имя конечного файла.

В итоге должен получиться следующий код:

// указание директории и имени нового файла на сервере
$new_file = "/upload_files/" .$_FILES["uploadfile" ]["name" ];

// копирование файла
if (copy($_FILES["uploadfile" ]["tmp_name" ], $new_file)) {
echo "Файл загружен на сервер" ;
} else {
echo "Ошибка при загрузке файла" ;
?>

Копирование файла, должно выполняться в существующую папку на сервере с имеющимися правами на создание в ней файлов.

В этом примере имя файла указывается тем же, как и у исходного загружаемого файла. В реале же очень часто имя задается в соответствии с собственными требованиями, чаще всего используя дату и время загрузки, что обеспечивает уникальность названия файла. Это позволяет свести хранение и обработку файлов к какому-либо единому стандарту. Здесь, конечно, появляются некоторые дополнительные задачи по хранению исходного названия в БД, если это нужно или определение расширения загружаемого файла . Но в таком случае будет меньше проблем с кодировкой названия фала, а так же цифровое название фала можно использовать для удобного формирования поддиректорий для хранения загружаемых фалов.

Функция copy() возвращает значение true, если копирование выполнено успешно и False при возникновении ошибки в процессе копирования.

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