Облако ссылок Добавить сайт Опубликовать Пользователи Категории

Сервис полезной информации


Размещайте полезную информацию и одновременно продвигайте свои проекты.


Узнать больше

Как на MVC с помощью PHP правильно загружать файлы на сервер. Часть Первая


X

Как на MVC с помощью PHP правильно загружать файлы на сервер. Часть Первая

Заходим в корень MVC и открываем файл .htaccess. В него нам потребуется добавить следующие параметры:

php_value upload_max_filesize 200M
php_value post_max_size 200M
php_value max_execution_time 1000000
php_value max_input_time 1000000

 

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

Теперь создадим HTML форму, в которой мы будем выбирать файл на загрузку. Создавать мы его будем в директории views/site. Создаем новый файл, даем ему название download_file.php. Он будет содержать следующий код:

<html>
<head></head>
<body>
<script>
    function CopyTxt() {
        function strtr(str, repl) {
            for (var i = 0; i < str.length; i++) {
                var f = str.charAt(i),
                   r = repl[f];
                if (r) {
                    str = str.replace(new RegExp(f, 'g'), r);
                }
            }
            return str;
        }

        var trans = {
            'А':'A', 'Б':'B', 'В':'V', 'Г':'G', 'Д':'D', 'Е':'E', 'Ё':'E', 'Ж':'Gh', 'З':'Z', 'И':'I', 'Й':'Y', 'К':'K', 'Л':'L', 'М':'M', 'Н':'N', 'О':'O', 'П':'P', 'Р':'R', 'С':'S', 'Т':'T', 'У':'U', 'Ф':'F', 'Х':'H', 'Ц':'C', 'Ч':'Ch', 'Ш':'Sh', 'Щ':'Sch', 'Ъ':'Y', 'Ы':'Y', 'Ь':'Y', 'Э':'E', 'Ю':'Yu', 'Я':'Ya', 'а':'a', 'б':'b', 'в':'v', 'г':'g', 'д':'d', 'е':'e', 'ё':'e', 'ж':'gh', 'з':'z', 'и':'i', 'й':'y', 'к':'k', 'л':'l', 'м':'m', 'н':'n', 'о':'o', 'п':'p', 'р':'r', 'с':'s', 'т':'t', 'у':'u', 'ф':'f', 'х':'h', 'ц':'c', 'ч':'ch', 'ш':'sh', 'щ':'sch', 'ъ':'y', 'ы':'y', 'ь':'y', 'э':'e', 'ю':'yu', 'я':'ya', ' ':'_'
        };

        var txt = strtr(document.getElementById('id1').value, trans);
        document.getElementById('id2').value = txt;
    }
</script>

 

В целях безопасности файлы на сервере рекомендуем хранить с названием на латинской раскладке. Чтобы избежать загрузки файла на кириллице  мы написали функцию CopyTxt. Функция берет строку из текстового поля id1 и с помощью функции strtr посимвольно заменяет кириллицу на латиницу, а затем возвращает строку в текстовое поле id2.

<h4>Загрузить файл</h4>
<br/>
Занятое место: <b><?= $hranilishe ?></b><br>
Свободное место: <b><?
    $svobod = 200 - $svobod;
    echo $svobod.' MB';
    ?></b><br>

Разрешеные форматы файлов: <b>*.PDF, *.TXT, *.DOC, *.DOCX, *.XLS, *.XLSX, *.ZIP, *.RAR, *.JPG, *.JPEG, *.PNG</b>
<br>
<?php if (isset($er_z) && is_array($er_z)): ?>
    <div style="padding:20px 20px 20px 20px; margin: 20px; background:#f1f1f1;">
        <ul style="color:red; width:100%;">
            <?php foreach ($er_z as $er_z): ?>
                <li style="line-height: 27px;"> - <?php echo $er_z; ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if (isset($errors) && is_array($errors)): ?>
    <div style="padding:20px 20px 20px 20px; margin: 20px; background:#f1f1f1;">
        <ul style="color:red; width:100%;">
            <?php foreach ($errors as $error): ?>
                <li style="line-height: 27px;"> - <?php echo $error; ?></li>
            <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

<?php if (isset($true) && is_array($true)): ?>
    <div style="padding:20px 20px 20px 20px; margin: 20px; background:#f1f1f1;">
        <ul style="color:green; width:100%;">
            <?php foreach ($true as $true): ?>
                <li style="line-height: 27px;"> - <?php echo $true; ?></li>
           <?php endforeach; ?>
        </ul>
    </div>
<?php endif; ?>

 

Мы выделяем пользователю под файлы 200мб. Поэтому пользователю важно знать, какое количество памяти у него занято, а какое свободно. Для этого мы выводим ему переменную  $hranilishe в которой считается размер всех загруженных пользователем файлов (сам расчет будет ниже). И переменную $svobod в которой считается свободное место.

В процессе загрузки файла или в момент отправки формы могут возникнуть ошибки (они будут описаны далее), они записываются в массивы er_z и error, а также будут выводиться сообщения об успешной загрузке, они записываются в массив true. Далее все эти массивы выводятся с помощью цикла foreach красным и зеленым цветом, для ошибок и сообщений соответственно.

 

<form method="post" action=""  enctype="multipart/form-data" style="width:100%; ">
    <table class="admin_table">
        <tr>
            <td>Заголовок*</td>
            <td><input id="id1" onkeyup="CopyTxt()" type="text" name="title" size="80" value="<?=$_POST['title']?>"></td>
        </tr>
        <tr>
            <td>Дата*</td>
            <td><input type="date" name="date" size="10" value="<?=$_POST['date']?>"></td>
        </tr>
        <tr>
            <td>Указать файл*</td>
            <td><input name="img_url" type="file" /></td>
        </tr>
        <tr>
            <td>Автоматический Url*</td>
            <td><input id="id2" type="text" name="url" size="80" value="<?=$_POST['url']?>" style="background: #ececec; color:#777;"></td>
        </tr>
    </table>
    <input class="button" type="submit" name="submit" value="Сохранить"><br><br><br><br>
</form>
</body>
</html>

 

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

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

 

 

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

<?php
return array(
    'download' => 'site/download',
    '' => 'site/index', // actionIndex в SiteController
);
?>

 

Теперь  заходим в папку controllers и открываем файл SiteController.php. Создаем метод actionDownload, в нем будет описана загрузка файлов с отображением самой страницы с формой.

<?
public function actionDownload()
{
    function HumanBytes($size)
    {
        $filesizename = array(" Bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB");
        return $size ? round($size / pow(1024, ($i = floor(log($size, 1024)))), 2) . $filesizename[$i] : '0 Bytes';
    }
    $sum = Page::checkDisk();
    $hranilishe = HumanBytes($sum);
    $svobod = explode(' ', $hranilishe);
    if ((trim($svobod[0])) == 0) {
        $svobod = 0;
    } else {
        if ($svobod[1] !== 'MB') {
            $svobod = 1;
        } else {
            $svobod = (real)trim($svobod[0]);
        }
    }
?>

 

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

Переменная $hranilishe, которая была использована на странице с формой, формируется здесь. С помощью функции checkDisk,(которую мы напишем позже в модели Page) . Она считает размер загруженных на сервер файлов и возвращает его в байтах. После этого мы применяем функцию HumanBytes и получаем размер в мегабайтах и других единицах измерения.

Далее формируем массив $svobod путем разбиения переменной $hranilishe через пробел. Далее если первый элемент полученного массива  равен нулю, что переменную $svobod  делаем равную нулю. Иначе проверяем вторую часть массива, если она равна МВ, то переменной $svobod присеваем  1, иначе присваиваем  переменной $svobod первую часть массива из которой убраны пробелы.

<?
    if ($svobod > 200) {
        $errors[] = 'Нет места в хранилище, свяжитесь с разработчиками!';
    } else {
        if (isset($_POST['submit'])) {
            $title = $_POST['title'];
            $date = $_POST['date'];
            $size = $_FILES['img_url']['size'];
            $url = $_POST['url'];
            $name = $_FILES['img_url']['name'];
            $tmp_name = $_FILES['img_url']['tmp_name'];

            // Флаг ошибок
            $errors = false;
            $true = false;
            $er_z = false;

            $inf = pathinfo($name);
            if (!$date) { $er_z[] = 'Укажите дату'; }
            if (!$url) {
                $er_z[] = 'Введите название новости вручную т.к. автоматический урл не может сгенирироваться';
            }
            if ($er_z == false) {
                $rash = $inf['extension'];
                if (Page::checkNameFile($url, $rash)) {
                    if ($rash === 'pdf') {
                        $true[] = 'Формат файла PDF';
                        $errors = true;
                    }

                    if ($rash === 'PDF') {
                        $true[] = 'Формат файла PDF';
                        $errors = true;
                    }

                    if ($rash === 'txt') {
                        $true[] = 'Формат файла TXT';
                        $errors = true;
                    }

                    if ($rash === 'doc') {
                        $true[] = 'Формат файла DOC';
                        $errors = true;
                    }

                    if ($rash === 'xls') {
                        $true[] = 'Формат файла XLS';
                        $errors = true;
                    }

                    if ($rash === 'docx') {
                        $true[] = 'Формат файла DOCX';
                        $errors = true;
                    }

                    if ($rash === 'xlsx') {
                        $true[] = 'Формат файла XLSX';
                        $errors = true;
                    }

                    if ($rash === 'zip') {
                        $true[] = 'Формат файла ZIP';
                        $errors = true;

                    }

                    if ($rash === 'rar') {
                        $true[] = 'Формат файла RAR';
                        $errors = true;
                    }

                    if ($rash === 'jpg') {
                        $true[] = 'Формат файла JPG';
                        $errors = true;
                    }

                    if ($rash === 'jpeg') {
                        $true[] = 'Формат файла JPG';
                        $errors = true;
                    }

                    if ($rash === 'png') {
                        $true[] = 'Формат файла PNG';
                        $errors = true;
                    }

?>

 

Методом POST получаем введенные в поля данные и сведения о файле. Записываем их в переменные. С помощью функции pathinfo() получаем массив $inf, который содержит информацию о пути загружаемого файла. Проверяем, все ли поля заполнены и выбран ли файл, если нет, то на странице отобразятся ошибки по неправильным полям. Если же все хорошо, то мы проходим дальше.

Из массива $inf передаем расширение загружаемого файла в переменную $rash.  Также проверяем, нет ли файла с таким именем среди загруженных ранее файлов, для этого используется функция checkNameFile, находящиеся в модели Page.

Проверяем расширение файла. Если расширение файла совпало с одним из «разрешенных», то переменной $errors присваиваем true.

<?

                    if ($errors == true) {
                        Page::downloadFile($url, $tmp_name, $rash);
                        $result = Page::add_news($title, $date, $url, $rash, $size);
                        if ($result == true) {
                            $true[] = 'Файл загружен.';
                        } else {
                            $errors[] = 'Ошибка загрузки!';
                        }

                    } else {
                        $errors[] = 'Загружаемые файлы могут быть в формате *.PDF, *.TXT, *.DOC, *.DOCX, *.XLS, *.XLSX, *.ZIP, *.RAR, *.JPG, *.JPEG, *.PNG';
                    }
                } else {
                    $errors[] = 'Такой файл уже есть в хранилище, измените Заголовок файла, и повторно выберите файл';
                }
            }
        }
    }

    require_once(ROOT . '/views/site/download_file.php');
    return true;
}
?> 

 

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

В конце подключаем вид страницы с формой.

Теперь опишем используемые функции в модели Page. Переходим в папку models и открываем файл Page.php. Добавляем в него следующие функции:

<?

public static function checkDisk(){
    $db = Db::getConnection();
    $query = "SELECT sum(size) FROM  `files`";
    $sum = $db->query($query)->fetchColumn();
    return $sum;
}

?>

 

checkDisk, эта функция возвращает сумму всех загруженных на сервер файлов.

 

<?

public static function checkNameFile($url, $rash){
    $filename = 'img/'.$url.'.'.$rash;
    if (file_exists($filename)) {
        return false; //"Файл $filename существует";
    } else {
        return true;//"Файл $filename несуществует";
    }

}

?>

 

checkNameFile, проверяет нет ли на сервере файла с таким же именем. Делается это с помощью функции file_exists, она проверяет, существует ли файл в указанном каталоге.

 

<?

public static function downloadFile($name, $tmp_name, $rash)
    {
        if ($rash == 'zip') {
            // Имя файла
            $filename = $tmp_name;
// Разбиваем файл на части по 10 Kb
            $piece = 250000;
// Открываем исходный файл для чтения
            $fp = fopen($filename, "r");
// Читаем содержимое файла в буфер
            $bufer = fread($fp, filesize($filename));
// Закрываем файл
            fclose($fp);
// Подсчитываем число частей, на которые необходимо разбить файл
            $count = (int)filesize($filename)/$piece;
            if((float)(filesize($filename)/$piece) - $count != 0) $count++;
// В цикле разбиваем содержимое файла в переменной
// $bufer на части
            for($i=0; $i<$count; ++$i)
            {
                $part = substr($bufer,$i*$piece,$piece);
// Сохраняем текущую часть в отдельном файле
                $fp = fopen("part/big_file.part".$i,"w");
                fwrite($fp,$part);
                fclose($fp);
            }
            $buffer = "";
            for($i=0; $i<$count; ++$i)
            {
                // Генерируем имя файла
                $filename = "part/big_file.part".$i;
                // Если такой файл существует,
                // добавляем его содержимое к $buffer
                if(file_exists($filename))
                {
                    $fp = fopen($filename,"r");
                    $buffer .= fread($fp,filesize($filename));
                    fclose($fp);
                }
                else
                {
                    // Если файла с таким именем не
                    // существует, выходим из цикла
                    break;
                }
                // Склеенные в переменной $bufer
                // части помещаем в конечный файл

                $fp = fopen('files/'.$name.'.'.$rash,"w");
                fwrite($fp, $buffer);
                fclose($fp);
                unlink($filename);
            }

        } else {
           $uploaddir = 'files/';
            $uploadfile = $uploaddir . basename($name . '.' . $rash);
            if (move_uploaded_file($tmp_name, $uploadfile)) {
                $true[] = 'Pагрузки!';
            } else {
                $errors[] = 'Ошибка загрузки!';
            }
        }
}

?>

 

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

 

<?
public static function add_news($title, $date, $url, $rash, $size)
    {
       // Соединение с БД
        $db = Db::getConnection();
        // Текст запроса к БД
        $sql = 'INSERT INTO files (title, date, url, rash, size) VALUES (:title, :date, :url, :rash, :size)';
        // Получение и возврат результатов. Используется подготовленный запрос
        $result = $db->prepare($sql);
        $result->bindParam(':title', $title, PDO::PARAM_STR);
        $result->bindParam(':date', $date, PDO::PARAM_STR);
        $result->bindParam(':url', $url, PDO::PARAM_STR);
        $result->bindParam(':rash', $rash, PDO::PARAM_STR);
        $result->bindParam(':size', $size, PDO::PARAM_STR);
        return $result->execute();
    }
}

?>

 

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

Grai Просмотров сегодня +3 16 июня 2017 команда сайта
Реклама помогает поддерживать
и развивать наш сервис.


Подробнее
(ссылка откроется в новой вкладке)
  Реклама