Статьи

Как загрузить файлы с CodeIgniter и AJAX

Асинхронная загрузка файлов может быть проблемой в лучшие времена, но в сочетании с CodeIgniter это может быть особенно неприятно. Наконец-то я нашел способ, который не только работает последовательно, но и соответствует шаблону MVC. Читайте дальше, чтобы узнать как!

Кстати, вы можете найти несколько полезных плагинов CodeIgniter и скриптов кода на Envato Market, так что просмотрите, что вы можете найти для вашего следующего проекта.


В этом руководстве мы будем использовать PHP-фреймворк CodeIgniter , JavaScript-фреймворк jQuery и скрипт AjaxFileUpload .

Предполагается, что у вас есть практические знания о CodeIgniter и jQuery, но предварительные знания об AjaxFileUpload не требуются. Также предполагается, что у вас уже установлена ​​установка CodeIgniter.

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

Вам также понадобится база данных и таблица, называемые files . SQL для создания указанной таблицы:

1
2
3
4
5
CREATE TABLE `files` (
  `id` int NOT NULL AUTO_INCREMENT PRIMARY KEY,
  `filename` varchar(255) NOT NULL,
  `title` varchar(100) NOT NULL
);

К концу урока ваша файловая структура должна выглядеть примерно так (исключая не измененные папки / файлы):

public_html /
— заявление/
—- контроллеры /
—— upload.php
—- модели /
—— files_model.php
—- взгляды/
—— upload.php
—— files.php
— css /
—- style.css
— файлы /
— JS /
—- AjaxFileUpload.js
—- site.js


Во-первых, нам нужно создать форму загрузки. Создайте новый контроллер с именем upload и в методе index отредактируйте представление view.

Ваш контроллер должен выглядеть так:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
class Upload extends CI_Controller
{
    public function __construct()
    {
        parent::__construct();
        $this->load->model(‘files_model’);
        $this->load->database();
        $this->load->helper(‘url’);
    }
 
    public function index()
    {
        $this->load->view(‘upload’);
    }
}

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

Создайте свое представление, upload.php . Этот вид будет содержать нашу форму загрузки.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<!doctype html>
<html>
<head>
    <script src=»https://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js»></script>
    <script src=»<?php echo base_url()?>js/site.js»></script>
    <script src=»<?php echo base_url()?>js/ajaxfileupload.js»></script>
    <link href=»<?php echo base_url()?>css/style.css» rel=»stylesheet» />
</head>
<body>
    <h1>Upload File</h1>
    <form method=»post» action=»» id=»upload_file»>
        <label for=»title»>Title</label>
        <input type=»text» name=»title» id=»title» value=»» />
 
        <label for=»userfile»>File</label>
        <input type=»file» name=»userfile» id=»userfile» size=»20″ />
 
        <input type=»submit» name=»submit» id=»submit» />
    </form>
    <h2>Files</h2>
    <div id=»files»></div>
</body>
</html>

Не забудьте поместить ajaxfileupload.js в js /.

Как видите, мы загружаем наши скрипты вверху; jQuery, AjaxFileUpload и наш собственный файл js. Здесь будет наш собственный JavaScript.

Затем мы просто создаем стандартную форму HTML. В пустом файле #files находится наш список загруженных файлов.

Чтобы это не выглядело так плохо, давайте добавим немного базового CSS в наш файл style.css в css /.

01
02
03
04
05
06
07
08
09
10
11
12
13
h1, h2 { font-family: Arial, sans-serif;
h2 { font-size: 20px;
 
label { font-family: Verdana, sans-serif;
input { padding: 3px 5px;
input[type=»file»] { padding-left: 0;
input[type=»submit»] { width: auto;
 
#files { font-family: Verdana, sans-serif;
#files strong { font-size: 13px;
#files a { float: right;
#files ul { list-style: none;
#files li { width: 280px;

Создайте и откройте site.js в js /. Поместите следующий код:

JavaScript захватывает отправленную форму, и AjaxFileUpload вступает во владение. В фоновом режиме он создает iframe и передает данные через него.

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

Затем мы проверяем наш возврат (который будет в JSON). Если ошибки не произошло, мы обновляем список файлов (см. Ниже), очищаем поле заголовка. В любом случае, мы предупреждаем ответное сообщение.


Теперь перейдем к загрузке файла. URL-адрес, на который мы загружаем, — это / upload / upload_file /, поэтому создайте новый метод в контроллере загрузки и поместите в него следующий код.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
public function upload_file()
{
    $status = «»;
    $msg = «»;
    $file_element_name = ‘userfile’;
     
    if (empty($_POST[‘title’]))
    {
        $status = «error»;
        $msg = «Please enter a title»;
    }
     
    if ($status != «error»)
    {
        $config[‘upload_path’] = ‘./files/’;
        $config[‘allowed_types’] = ‘gif|jpg|png|doc|txt’;
        $config[‘max_size’] = 1024 * 8;
        $config[‘encrypt_name’] = TRUE;
 
        $this->load->library(‘upload’, $config);
 
        if (!$this->upload->do_upload($file_element_name))
        {
            $status = ‘error’;
            $msg = $this->upload->display_errors(», »);
        }
        else
        {
            $data = $this->upload->data();
            $file_id = $this->files_model->insert_file($data[‘file_name’], $_POST[‘title’]);
            if($file_id)
            {
                $status = «success»;
                $msg = «File successfully uploaded»;
            }
            else
            {
                unlink($data[‘full_path’]);
                $status = «error»;
                $msg = «Something went wrong when saving the file, please try again.»;
            }
        }
        @unlink($_FILES[$file_element_name]);
    }
    echo json_encode(array(‘status’ => $status, ‘msg’ => $msg));
}

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

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

Далее мы пытаемся загрузить файл. в случае успеха мы сохраняем заголовок и имя файла (переданные через возвращенный массив данных).

Не забудьте удалить временный файл с сервера и отобразить JSON, чтобы мы знали, что произошло.

В соответствии с шаблоном MVC, наше взаимодействие с БД будет обрабатываться моделью.

Создайте files_model.php и добавьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
class Files_Model extends CI_Model {
 
    public function insert_file($filename, $title)
    {
        $data = array(
            ‘filename’ => $filename,
            ‘title’ => $title
        );
        $this->db->insert(‘files’, $data);
        return $this->db->insert_id();
    }
 
}

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


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

Откройте site.js и добавьте следующий код в конец файла, ниже всего остального.

Это просто вызывает URL и вставляет возвращенные данные в div с идентификатором файлов.

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

URL, который мы вызываем для получения списка файлов: / upload / files /, поэтому создайте новый метод с именем files и поместите его в следующий код:

1
2
3
4
5
public function files()
{
    $files = $this->files_model->get_files();
    $this->load->view(‘files’, array(‘files’ => $files));
}

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

Наша модель обрабатывает поиск списка файлов. Откройте файл files_model.php и добавьте в get_files() .

1
2
3
4
5
6
7
public function get_files()
{
    return $this->db->select()
            ->from(‘files’)
            ->get()
            ->result();
}

Все очень просто: выберите все файлы, хранящиеся в базе данных.

Нам нужно создать представление для отображения списка файлов. Создайте новый файл с именем files.php и вставьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<?php
if (isset($files) && count($files))
{
    ?>
        <ul>
            <?php
            foreach ($files as $file)
            {
                ?>
                <li class=»image_wrap»>
                    <a href=»#» class=»delete_file_link» data-file_id=»<?php echo $file->id?>»>Delete</a>
                    <strong><?php echo $file->title?></strong>
                    <br />
                    <?php echo $file->filename?>
                </li>
                <?php
            }
            ?>
        </ul>
    </form>
    <?php
}
else
{
    ?>
    <p>No Files Uploaded</p>
    <?php
}
?>

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


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

Добавьте следующее в функцию готовности документа:

Всегда полезно получить подтверждение пользователя при удалении информации.

При нажатии на ссылку для удаления отображается окно подтверждения с вопросом, уверен ли пользователь. Если они есть, мы делаем вызов /upload/delete_file , и в случае успеха мы /upload/delete_file из списка.

Как и выше, URL, который мы вызываем, это /upload/delete_file/ , поэтому создайте метод delete_file и добавьте следующий код:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
public function delete_file($file_id)
{
    if ($this->files_model->delete_file($file_id))
    {
        $status = ‘success’;
        $msg = ‘File successfully deleted’;
    }
    else
    {
        $status = ‘error’;
        $msg = ‘Something went wrong when deleteing the file, please try again’;
    }
    echo json_encode(array(‘status’ => $status, ‘msg’ => $msg));
}

Опять же, мы позволяем модели выполнять тяжелую работу, повторяя результаты.

Теперь мы находимся на последней части головоломки: наши последние два метода.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
public function delete_file($file_id)
{
    $file = $this->get_file($file_id);
    if (!$this->db->where(‘id’, $file_id)->delete(‘files’))
    {
        return FALSE;
    }
    unlink(‘./files/’ . $file->filename);
    return TRUE;
}
 
public function get_file($file_id)
{
    return $this->db->select()
            ->from(‘files’)
            ->where(‘id’, $file_id)
            ->get()
            ->row();
}

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

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


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

Однако у этого метода есть несколько недостатков:

  • Вы можете загружать только один файл за раз, но это легко исправить, используя сервис типа Uploadify .
  • В скрипт не встроен индикатор выполнения.
  • Мы могли бы уменьшить количество вызовов SQL, обновляя файлы div при загрузке файлов, вместо полной их замены.

Спасибо за прочтение!