Урок 7 — Класс Upload. Загрузка файлов на сервер.

Продолжаем знакомство с классами фреймворка Codeigniter 2.1.0. И в этом уроке научимся загружать файлы на сервер.
Будем загружать изображения, выставлять различные настройки и записывать в базу данных название загруженного изображения. В этом нам поможет класс Upload.

Выставляйте качество 480р.

Если Вы хотите выучить весь фреймворк CodeIgniter и создавать мощные и функциональные сайты — Вам сюда.

В прошлом уроке мы создавали постраничную навигацию на сайте и если Вы не знаете как это делать, то пройдите данный урок 😉

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

Новый вид (например upload_view):


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Title</title>
</head>

<body>

<form method="post" action="" enctype="multipart/form-data">
<input type="file" name="userfile" />
</form>

</body>
</html>

Action для формы пропишем чуть позже. Важно не забыть прописать для формы enctype=»multipart/form-data» — это нужно для загрузки файлов на сервер. Так же важно для поля с типом file придать имя (name) именно userfile.
Далее идем в контроллер, у меня это будет контроллер first. Создаем там новую функцию, скажем, upload_photo. Загрузим в этой функции наш вид с формой.

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

Контроллер:

function upload_photo()
{

    if(isset($_POST['download'])) // если кнопка нажата то..
    {
        // тут будет происходить загрузка файла на сервер
    }
    else
    {
        $this->load->view('upload_view'); // если кнопка загрузки не нажата, грузим просто вид
    }

}

Вот. Теперь давайте приступим к загрузке файла. Сначала нам нужно создать массив с настройками, загрузить библиотеку Upload, указав параметром эти настройки и вызвать соответствующую функцию загрузки.

Контроллер:


function upload_photo()
{
    if(isset($_POST['download']))
    {
        $config['upload_path'] = './img/photos/'; // путь к папке куда будем сохранять изображение
	$config['allowed_types'] = 'gif|jpg|png'; // разрешенные форматы файлов
	$config['max_size']	= 2000; // максимальный вес файла
        $config['encrypt_name'] = TRUE; // переименование файла в уникальное название
	$config['remove_spaces'] = TRUE; // убирает пробелы из названия файлов

	$this->load->library('upload', $config); // загружаем библиотеку

        $this->upload->do_upload(); // вызываем функцию загрузки файла
    }
    else
    {
        $this->load->view('upload_view'); // если кнопка загрузки не нажата, грузим просто вид
    }
}

Папка img хранится в корне сайта и внутри нее создана папка photos. То есть создавайте папку для изображений там где у Вас папка application, system, там же создавайте папки для CSS и Java скриптов, то есть на одном уровне.

Перечислять разрешенные форматы можете через |, максимальный вес файла указан в КБ. Замена пробелов в названии файлов на нижнее подчеркивание — рекомендую всегда оставлять, так безопаснее. Да, и переименование файлов тоже всегда ставьте в TRUE — полезная штука. Так же есть еще разные настройки, посмотреть можете тут.
Если все сделано правильно, то в принципе все готово, осталось прописать action для нашей формы.
Пишем так:


<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Title</title>
</head>

<body>

<form method="post" action="<?=base_url();?>index.php/first/upload_photo" enctype="multipart/form-data">
<input type="file" name="userfile" />
</form>

</body>
</html>

В action указываем контроллер и его функцию, которая будет, собственно, загружать файлы на сервер. В моем случае это контроллер first и его функция upload_photo.

Что же такое =base_url(); — этой конструкцией мы подставляем основной адрес Вашего сайта в нужное место.
Это тоже самое если бы мы написали: http://localhost/cilessons/ вместо =base_url();

Ваш base_url прописан в файле, который находится в папке application->config и файл config.php, самая первая настройка.
Чтобы пользоваться этой функцией (base_url();) Вам нужно загрузить хелпер URL.

Заходим в папку application->config и открываем файл autoload.php и там ищем такую строку и пишем так:

$autoload['helper'] = array('url');

Вот и все. Пробуйте загрузить что-нибудь.
Теперь еще не менее интересный момент. Наверняка при загрузке файла нужно занести его название в БД для дальнейшего вывода на экране. Например, у Вас есть таблица photos с 2 полями id и img. И вот в поле img нужно записать название загруженного файла. Как же это сделать? Все очень просто.

Делаем такие изменения в контроллере:

function upload_photo()
{
    if(isset($_POST['download']))
    {
        $config['upload_path'] = './img/photos/'; // путь к папке куда будем сохранять изображение
	$config['allowed_types'] = 'gif|jpg|png'; // разрешенные форматы файлов
	$config['max_size']	= 2000; // максимальный вес файла
        $config['encrypt_name'] = TRUE; // переименование файла в уникальное название
	$config['remove_spaces'] = TRUE; // убирает пробелы из названия файлов

        $this->load->library('upload', $config); // загружаем библиотеку

        $this->upload->do_upload(); // вызываем функцию загрузки файла

        /* Начало занесения имени файла в БД*/
        $upload_data = $this->upload->data(); // получаем информацию о загруженном файле
        $add['img'] = $upload_data['file_name']; // сохраняем имя файла в элемент массива add
        $this->db->insert('photos',$add); // заносим это значение в таблицу photos
        /* Конец занесения имени файла в БД*/
    }
    else
    {
        $this->load->view('upload_view'); // если кнопка загрузки не нажата, грузим просто вид
    }
}

Ну вот и готово. функция — this->upload->data(); — возвращает информацию о загруженном файле в виде массива. Элементы этого массива можете найти в документации почти в самом низу. В массив add заносим имя загруженного файла, взятое из массива с информацией, ну а дальше занесение в базу.

Надеюсь у Вас получилось :)

Если урок Вам был полезен, нажмите на любую кнопку ниже— буду благодарен :) Всем удачи и следите за ходом событий ;)

Комменты

  • спасибо за урок, очень просто, без лишнего, сходу получилось

    поставьте себе донат пейпалом, чтобы была возможность отблагодарить не из СНГ

  • Disallowed Key Characters. пишет после нажатия кнопки(локальный сервер)

    • Проблема решена.Возможно в коде были пробелы — скопировала код с этой страницы(ранее писала сама по видео) и все заработало.Кстати, тут не хватает кнопочки»загрузить»

  • Здравствуйте, а как загрузить несколько файлов сразу?

  • а то я прописал формат и пытаюсь загрузить mp4 на сервер локальный а в phpmyadmin и в папку не грузит

  • а если я хочу загрузить на сервер видео

  • Как сделать загрузку нескольких файлов сразу?

  • Все сделал вроде бы как надо, но в результате перезапроса страницы опять загружается этот же файл (то есть обратно прихожу методом POST). В просто процедурном php для этого отправляю заголовок header(‘Location:…..’), а тут что-то не могу избавиться. Подскажите.

    • Дмитрий Валак: 16-10-2013 в 10:49

      Здравствуйте. А если воспользоваться функцией redirect(); которую нам предлагает помощник url? Попробуйте

  • Здравствуйте. Не работает, однако. Есть форма, на ней кнопка — жму, выбираю файл(gif)(размер 4 кБ)- ок. И всё. В базе пусто, в папке пусто, в голове тоже. Надо что-то делать, уже…

  • Дим, хороший урок, спасибо, смотрел с удовольствием. Ребят, смотрите и читайте внимательнее. ZIP и не будет грузиться, потому что не указан в типах принимаемых файлов, а указаны только картинки:

    $config[‘allowed_types’] = ‘gif|jpg|png';

    Нужен другой тип — добавьте расширение в этот параметр

  • Загрузить — загрузили, а как удалить файл? helper (file) и фунцкия delete_files('path') не прокатывает(((( удаляет все файлы в папке, а не тот один, который нужен

  • Да правильно Д.Валак такую строчку не упустил  $this->upload->do_upload (); это есть .Однако zip файлы у меня не загружаются. Ну да ладно может сам что то упустил

  • Для тех. у кого в папке загрузки после загрузки файла —  пусто. объясню. что нужно поставить еще строчку:
    $this->upload->do_upload(); // вызываем функцию загрузки файла
    Сам мучился. пытаясь сделать по видеороку Дмитрия, но там этот момент почему-то упущен…

  • Приветствую.Поставил расширение для загрузки файлы pdf,zip. файл pdf загрузился, zip — нет.Хотя программа написали загрузка произведена его не было в папке загрузки.в базе тоже не было названия.Может загружаются только рисунки,а для загрузки zip надо еще какие то настройки? Пробовал на локальном сервере и на хостинге одно и тоже  

  • Дмитрий, добрый день . При использовании класса Upload  столкнулся с проблемой загрузки изображений на реальный сервер (в бд запись вносится но в папке загрузки пусто, атрибуты выставлены правильно), на денвере все грузится. Подскажите как быть!

    • Дмитрий Валак: 21-11-2012 в 11:26

      Здравствуйте.
      Возможно, что-то с путем к папке, куда совершается загрузка, поэтому и не загружается

  • По мне Вы слишком заморочены на мелочах, всегда ставлю эти 2 конфига в тру и все работает как надо.

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

    убирает пробелы из названия файлов - заменить на - заменяет знак пробел символом _

    Ибо при создании web-проектов, работая даже на "буржуев", такие мелочи могут быть не простительны (вплоть до потери клиента, в крупном проекте, т.к щепетильны они ко всему).  Да и жизнь наша с Вами, состоит из мелочей.
    К тому же, если вы используете CI, то лучше отходить от привычных методов получения GET или POST данных, для чего в CI, и предусмотрен класс INPUT, который позволяет более удобно использовать данные без ручной проверки их существования.
    Т.е. вместо того, чтобы получать данные напрямую $_POST['download'] функция $this->input->post('download' ) проверяет их существование, и в соответствии с этим возвращают FALSE или данные. При этом достаточно заменить конструкцию на соответствующую:

    if($this->input->post('download'))
    Также, мы можем подключить в конфиге защиту от xss-атак,
     обеспечив более надежную проверку POST данных 
    ($this->input->post('download', TRUE))
    

    Вот так вот..
     
     

    • Дмитрий Валак: 26-06-2012 в 8:31

      Да, исправлю.
      И насчет класса инпут я знаю, просто если этого нету в данном уроке, это не значит что я об этом не рассказываю.
      Программа полного курса была сделана в виде поэтапного обучения, дабы не сваливать все сразу в кучу.

  • Пробелы то, все равно убраны.

    Они не убраны они заменены!!!!, и разница достаточная. Особенно, если есть необходимость в сравнении файла загруженного на сервер и файла исходного на диске пользователя.
    Приведу самый простой пример, дабы показать, что использовать этот параметр, необходимо крайне осторожно.
    Если файл "z 1.jpg", который при параметре:

    $config['remove_spaces'] = TRUE; // убирает пробелы из названия файлов

    получает имя: z_1.jpg.
    Возникает вопрос, что прикажете делать пользователю, если ему необходимо загрузить файл z_1.jpg??? (т.е. в имени которого есть подчеркивание) Как определить который фал имеет ценность для пользователя О_о?
    Получается, копия этого файла, (допустим с нарощеным префиксом  z_12.jpg), но в действительности, этот файл не содержит ту ин-фу, которая была необходима пользователю.
    По этому, есть разница в удалении и в замене. Вот так вот.

    • Дмитрий Валак: 25-06-2012 в 21:50

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

  • $config['remove_spaces'] = TRUE; // убирает пробелы из названия файлов

    И

    Убирание пробелов из названия файлов — рекомендую всегда оставлять, так безопаснее. Да, и переименование файлов тоже всегда ставьте в TRUE — полезная штука. Так же есть еще разные настройки, посмотреть можете тут.

    Да уж… А мне казалось всегда, что данный параметр (remove_spaces) транслирует пробелы в символы подчеркивания, так что лучше читайте мануалы, чем давайте неверную информацию людям.

    If set to TRUE, any spaces in the file name will be converted to underscores. This is recommended.

    • Дмитрий Валак: 25-06-2012 в 16:47

      Пробелы то, все равно убраны.
      И я сам знаю, что для меня лучше 😉

  • Тряяяяхуууу! Все получилось, весь мозг себе вынес со стандартной документацией.