Загрузка файлов на сервер.
26.12.2019Довольно часто возникает необходимость дать возможность пользователям добавлять информацию на сайт в формате загрузки файлов.
Это могут как изображения, так и документы различных форматов.
Ниже рассмотрим два варианта добавления информации на сервер, разные по способу и реализации, но со схожим результатом.
1. Первый способ, который будет рассмотрен — загрузка с помощью простой HTML формы с обработкой входящей информации средствами PHP.
Для реализации задачи будет использована простая форма с двумя полями «Описание» (ведь нужно же передать на сервер информацию о том что загружается) и «Выбор файла»…
Пропускаю код страницы содержащий заголовки,стили и кодировку — тут каждый сам лепит как хочет. Получается такая форма:
<form name="Upload" method="post" action="upload_plus.php" enctype="multipart/form-data" id="Form1"> <table width="399" height="203" border="0" bordercolor="#99CCFF" bgcolor="#E2E2E2"> <tr> <TD> <div align="center"><strong>ЗАГРУЗКА НОВОГО ФАЙЛА НА СЕРВЕР</strong></div> </TD></tr> </tr> <td height="170"> Описание: <input name="opis" type="text" id="opis" onChange="Submit.disabled=false;" onClick="Submit.disabled=false;" size="42"> <strong><font size="2">Файл:</font></strong> <input type="file" id="userfile[]" size="35" name="userfile[]" > <p align="left"> <input name="Submit" type="Submit" disabled="true" value="Сохранить запись " ></p> </td> <script type="text/javascript"><br /> function EnableBox(form, elem, evt){<br /> var char = evt.keyCode;<br /> if(char == 13){<br /> form.submit();<br /> return false;<br /> }<br /> return true;<br /> }<br /> </script></table> </form>
Как Вы наверное заметили, в форме присутсвует табличная верстка, — просто мне так было удобно, можете сделать это DIV-ами.
Кроме того, наверняка обратили внимание на присутсвующий в коде формы javascript, — это обработчик нажатия клавиши Enter, которая в данном случае заменяет клик мышью по кнопке, если пользователю удобнее навигация с помощью клавиши Tab….
В объявлении формы присутсвует такая стока: method=»post» action=»upload_plus.php» enctype=»multipart/form-data«.
Данной строкой мы даем знать браузеру, что в форме передается содержимое разного типа, метод отправки скрипту-обработчику и собственно имя обработчика формы.
Обработчик же должен принять данные из формы и выполнить загрузку файла на сервер. Код обработчика содержит следующие параметры (я их так назвал): $uploaddir — полный путь к каталогу хранения файлов на сервере
$updir — имя целевого каталога
$allowed — разрешенные к загрузке типы файлов
$max_size — максимально разшененный размер загружаемого файла
$text — полученное из формы текстовое значение
В коде приведенном ниже, Вы наверняка обратите внимание на переменную «Х», которая в ходе проверки будет учеличиваться на еденицу ($x=$x+1;), — это сделано для того, чтобы исключить дублирование имен файлов.
Таким образом, в процессе загрузки, принимающий php-скрипт заменяет имя загружаемого файла на цифровое значение.
Файлы сохраняются под именами вида «1.doc»,»2.doc» (или другого расширения), что позволяет дать каждому файлу уникальное имя.
После загрузки скрипт сообщает об успешной (или нет) загрузке файла и URL до файла на сервере. Код загрузчика:
$uploaddir = 'E:/site/files/'; $updir = '/files/'; $allowed = array('doc','xls','zip','pdf','rar','jpg','bmp','gif','chm','exe');// разрешенные типы файлов $max_size = 1024*300*1024; // максимальный размер файла $x=0; $text = $_REQUEST["opis"]; if ($text == "") { echo 'НЕ ВВЕДЕНО ОПИСАНИЕ ЗАГРУЗКИ!'.' '."\n"; $err_2=1; } else { $err_2=0 ;} if ($err_2==0){ # Процесс выполнения загрузки файла и проверка на ошибки if (isset($_FILES['userfile'])) { foreach ($_FILES['userfile']['error'] as $i => $error) { if ($_FILES['userfile']['size'][$i] == 0) { echo 'НЕ ВЫБРАН ФАЙЛ ДЛЯ ЗАГРУЗКИ!'.' '."\n";} if ($error == 0 && $_FILES['userfile']['size'][$i] <= $max_size) { $file_ext = pathinfo($_FILES['userfile']['name'][$i],PATHINFO_EXTENSION); $file_name = basename($_FILES['userfile']['name'][$i],'.'.$file_ext); if (in_array(strtolower($file_ext),$allowed)) { $x=$x+1; $new_base = $x.'.'.$file_ext; while (file_exists($uploaddir.$new_base)) { $x=$x+1; $new_base = $x.'.'.$file_ext; } $endurl='https://'.$_SERVER['SERVER_NAME'].$updir.$new_base; if (move_uploaded_file($_FILES['userfile']['tmp_name'][$i],$uploaddir.$new_base)) { chmod($uploaddir.$new_base, 0644); echo 'Загружен файл: '.$_FILES['userfile']['name'][$i].' '."\n"; echo 'Описание: '.$text.' '."\n"; }}else{echo 'Загрузка файлов этого типа не разрешена или файл слишком большого размера.'.' '."\n";} }}}}
На этом завершим описание первого способа.
2. Второй способ, который будет рассмотрен — загрузка с помощью формы, основой обработки которой будет плагин uploadify JQuery, с flash элементом в структуре формы.
Этот спопоб намного сложнее приведенного выше, но и выглядит приятнее и возможностей больше.
Следует сказать, что 2-ой способ приведу ASIS, т.е. так как я его использовал.
Здесь присутствует связка с базой данных, ajax, комбобокс, проверка целостности файла по хэшу MD5 и проверка перед запись в базу данных по структуре информации переданной из формы (это может быть как загрузка файла, так и запись в виде ссылки). На страницы целевого сайта выводится вся необходимая информация, но об этом сейчас не будем, — запросы к БД Вы писать, надеюсь, умеете 🙂
И так. Код формы приведу урезано, — по необходимости создадите свою структуру, но смысл будет ясен.
<h3>Загрузка информации на сайт</h3> <form> <div id="queue"></div> <strong>Раздел:</strong> <select name="razd" id="list" style="width: 293px;"onchange="idx=this.selectedIndex;razdel();"> <option value=0 style="color:red;">Выберите раздел !</font></option> <option value=1>Фотографии</option> <option value=2>Документы</option> <option value=3>Ссылки</option> </select> <strong>Описание: </strong> <input name="subj" type="text" id="subj" size="43"> <strong>Ссылка :</strong> <input type="text" size="43" id="url" value="" disabled> <input name="file_upload" type="file" id="file_upload" multiple="false" > </form>
Выбор раздела сразу же обрабатывается скриптом, который возвращает в переменную value выбранного пункста.
Описание — текстовое поле, для ввода комментария.
Ссылка — поле для указания URL , если создается запись с вложением ссылки на какой-то ресурс.
Обратите внимание на поле для файла. Оно вроде бы есть в коде, но с использованием плагина uploadify оно не выводится, пока не выбран файл. Выбранный файл отобразится только после нажатия кнопки «Выберите файл» и собственно его выбора.
Здесь есть небольшой нюанс — кодом который будет ниже, предусмотрен «костыль» — файлы в окне выбора не будут отображаться пока не выбран раздел для размешения. Своего рода «защита от дурака».
Максимальный размер файла заданный в приведенном выше коде, должен быть не более разрешенного в настройках Web-сервера.
Для придания уникальности шифрования файла md5 используем «соль», роль которой выполнит текушее время.
Теперь, после формы, на странице необходимо подключить скрипт загрузки.
<script type="text/javascript"><br /> <?php $timestamp = time();?><br /> $(function() {<br /> $('#file_upload').uploadify({<br /> 'formData' : {<br /> 'method' : 'post',<br /> 'dataType': "text",<br /> 'timestamp' : '<?php echo $timestamp;?>',<br /> 'token' : '<?php echo md5('unique_salt' . $timestamp);?>'<br /> },<br /> 'auto' : false, // запретить автозагрузку файла на сервер (ждем команды)<br /> 'fileTypeExts' : 'Не выбран раздел' ,<br /> 'buttonText' : 'Выберите файл',<br /> 'swf' : 'uploadify.swf',<br /> 'uploader' : 'uploadify.php',<br /> 'checkExisting' : 'check-exists.php',<br /> 'removeCompleted' : false,<br /> 'multi' : false,<br /> 'uploadLimit' : 1,<br /> 'onUploadComplete' : function(data) {<br /> $('#file_upload').uploadify('settings','uploadLimit','0');<br /> $('#outfile').empty();<br /> $('#outfile').text('Запись данных выполнена!');<br /> }<br /> });<br /> });<br /> </script>
Не буду расписывать все параметры uploadify, все доступно в интернете. Форма описана, скрипт обработки приведен. Далее выведем кнопки:
<button id="ok" class="b1" onclick="javascript: a();">Выполнить загрузку</button> <button id="new" class="b1" onclick="javascript:b();">Новая загрузка</button> <div id="outfile" style="font-weight: bold;"></div>
Обратили внимание на функции javascript в обработчиках кнопок? Их описания еще нет. Распишем. Первое и важное здесь — необходимо подсключить jquery и класс uploadify, поэтому в head страницы обязательно нужно их подключить.
Подключаем:
<head> <title>Загрузка информации на сайт</title> <script src="jquery-1.11.0.min.js" type="text/javascript"></script> <script src="jquery.uploadify.min.js" type="text/javascript"></script> <link rel="stylesheet" type="text/css" href="uploadify.css">
Туда же нужно включить и скрипты обработки формы (выбора раздела и кликов по кнопкам)
<script type="text/javascript"><br /> var idx=0;<br /> function a() {<br /> opisan=$('#subj').val();<br /> if(idx>0 && opisan !=""){<br /> if(idx<3){ // потому что 3 пункт у нас не является загрузкой файла $('#file_upload').uploadify('settings', 'formData', {'subj' : $('#subj').val() }); $('#file_upload').uploadify('settings', 'formData', {'id' : idx}); $('#file_upload').uploadify('upload'); $('#file_upload').uploadify('disable', true); } if(idx>2){ // отправляем обработчику только текстовую информацию<br /> $('#file_upload').uploadify('disable', true);<br /> $.get("uploadify.php", {<br /> id:idx,<br /> subj: $('#subj').val(),<br /> link: $('#url').val()<br /> }<br /> );<br /> }<br /> document.getElementById('ok').disabled=true;<br /> document.getElementById('new').disabled = false;<br /> }else{<br /> alert('Введены не все данные !');}<br /> }<br /> function b() { //новая загрузка, очистка формы и переменных<br /> $('#file_upload').uploadify('cancel');<br /> if(idx<5){ $('#file_upload').uploadify('disable', false) }; document.getElementById('new').disabled=true; document.getElementById('ok').disabled = false; $('#outfile').empty(); $('#subj').val(''); $('#url').val(''); } function razdel() { //меняем настройки uploadify от типа загрузки if(idx==0){ $('#file_upload').uploadify('settings','fileTypeExts','*.netfaila;'); $('#file_upload').uploadify('settings','fileTypeDesc','Не выбран раздел'); $('#file_upload').uploadify('disable', true); document.getElementById('url').disabled = true; } if(idx==1){ $('#file_upload').uploadify('settings','fileTypeExts','*.jpg'); $('#file_upload').uploadify('settings','fileTypeDesc','Изображения и фотографии'); $('#file_upload').uploadify('disable', false); document.getElementById('url').disabled = true; } if(idx==2){ $('#file_upload').uploadify('settings','fileTypeExts','*.jpg; *.jpeg; *.docx; *.doc; *.xlsx; *.xls; *.pdf; *.ppsx; *.pptx; *.ppt; *.zip; *.7z; *.rar'); $('#file_upload').uploadify('settings','fileTypeDesc','Документы'); $('#file_upload').uploadify('disable', false); document.getElementById('url').disabled = true; } if(idx==3){ $('#file_upload').uploadify('disable', true); document.getElementById('url').disabled = false; } } </script>
На этом формирование страницы для выбора загрузки 2-м способом завершено. CSS и разметка страницы тут не учитывается.
Теперь приступим к обработке информации от формы.
Для этого служат указанные в параметрах выше описанной страницы скрипты : uploadify.php и check-exists.php.
Файл check-exists.php служит для проверки путей и наличия в целевом каталоге такого же имени файла. В прочем проверку имени можно и не делать, поскольку, как я Вам покажу дальше, имя файла будет генерироваться по хэшу md5 текушего времени в формате microtime, но таков уж uploadify — требует возврата значения об ошибке…
Приведу код моего php-скрипта как есть… Разобраться не трудно.
$data= date("Y.m.d"); $dbhost='localhost'; $dbuser='user; $dbpassword='pass'; $database='dbname'; $db = mysql_connect($dbhost, $dbuser, $dbpassword) or die("Ошибка соединения: " . mysql_error()); mysql_select_db($database) or die("Ошибка соединения с базой данных"); mysql_query("SET NAMES utf8"); $razd=$_POST['id']; if($razd == ""){ $razd=$_GET['id']; } if ($razd<3){ $subj=$_POST['subj']; $targetFolder = '/files/'; // каталог назначения загруженных файлов $verifyToken = md5('unique_salt' . $_POST['timestamp']); if (!empty($_FILES) && $_POST['token'] == $verifyToken) { $tempFile = $_FILES['Filedata']['tmp_name']; $targetPath = $_SERVER['DOCUMENT_ROOT'] . $targetFolder; // проверка типа файла $fileTypes = array('jpg','jpeg','docx','doc','xlsx','xls','pdf','ppsx','pptx','ppt','zip','7z','rar','avi','mpg','mpeg','exe','msi'); // разрешенные расширения $fileParts = pathinfo($_FILES['Filedata']['name']); $file_ext = $fileParts['extension'] ; //расширение загружаемого файла $filename = md5(microtime()); //генерация нового имени $new_file = $filename.'.'.$file_ext; $targetFile = rtrim($targetPath,'/') . '/' . $new_file; //переименованный файл подготовлен if (in_array($fileParts['extension'],$fileTypes)) { move_uploaded_file($tempFile,$targetFile); // если тип файла разрешен - заливаем echo '1'; // ключ выполненной операции $endurl='https://'.$_SERVER['SERVER_NAME'].$targetFolder.$new_file; //сформировал URL загруженного файла для браузера //Теперь можно делать запись в БД $ins="insert into content(razdel,subject,link,data) values('$razd','$subj','$endurl','$data')"; mysql_query($ins); }} }else{ //запись без загрузки файла $url=$_GET['link']; $subj=$_GET['subj']; $ins="insert into content(razdel,subject,link,data) values('$razd','$subj','$url','$data')"; mysql_query($ins); }
Вот и всё! Удачных реализаций!
И не забудьте поставить LIKE кнопкой соц.сети справа от записи.