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

Ещё пока нет комментариев, будь первым!
🔔 Отдохните не много, может Вам будет интересно прочитать статьи пользователей нашего сайта.
Как на MVC и PHP создать систему восстановления доступа с отправкой пароля на адрес электронной почты
Недостатки раскрутки групп Вконтакте специальными сервисами
Решил и я написать статью о том, как покупал сайт на бирже ТЕЛДЕРИ
Как создать модуль онлайн консультации с использованием чата на ajax и php
Тег area - это область ссылки
Как на MVC с помощью PHP загружать изображения на сервер
Тег audio - это управление аудиофайлом
Тег b - это полужирный шрифт
Тег datalist - это список возможных вариантов
Как проверить радио кнопку checkbox без перезагрузки страницы ajax php
Тег code - это отображение программного кода
Как на MVC с помощью PHP и MySQL создать счетчик просмотров страниц