Изучая веб-программирование, я не нашел внятного решения проблемы оформления загрузки файла на сервер при помощи одной кастомной кнопки.
Предлагаю на суд сообщества свой велосипед. На написание данного текста вдохновил Способ №5 из материала Делаем красивый input[type=file] для адаптивного сайта… И да — все работает в IE, начиная с 9 версии.
Цель: создать свою кнопку/элемент управления по нажатию которой происходит загрузка файла на сервер (либо иные, предусмотренные разработчиком, файловые операции).
Инструменты: CSS, PHP, JavaScript.
Используемые технологии: Ajax, через скрытый iframe.
Преамбула
Из кода для упрощения сознательно выкинуты все процедуры проверки принятого файла и try-catch вызовов функций, так как эти моменты не являются темой данной статьи. Также не охватывается момент по предотвращению звукового сигнала в IE. В работе используем технологию Ajax, подразумевающую, что у нас есть основная страница, осуществляющая взаимодействие с пользователем(front-end) и скрипт на сервере, обрабатывающая наши запросы(back-end)
Технология работы
1. На главной странице создаем «form action» Делаем ей target на скрытый фрейм, который создаем статически (или динамически). Создаем два «input» с типом «file» и «submit», даем им «id», помещаем их в «div», который спрячем со страницы стилем. Все эти элементы не видимы для пользователя и не воспринимают каких-либо его действий.
2. Начинаем «магию». Для «input» с типом «file» на событие по изменению вешаем вызов функции onchange=«LoadFile();».
3. На главной странице создаем кнопку. Навешиваем ей на событие нажатия кнопки мыши вызов функции onclick=«FindFile();».
4. В функции FindFile() имитируем клик на «input» с типом «file». То есть при нажатии на нашу кнопку вызывается стандартный диалог выбора файла. Как только пользователь выбрал файл, срабатывает событие onchange и вызывается функция LoadFile(). В функции LoadFile() имитируем клик на «input» с типом «submit».
5. Форма формирует POST запрос с именем файла к нашему back-end скрипту, который осуществляет все проверки по безопасности и загрузку файла. После этого скрипт вызывает callback функцию главной страницы, которой сообщает о результате выполнения.
Собственно все. Для примера приведены четыре основных файла, код которых приведён ниже:
css/style.css – стили главной страницы
view/upload.php – back-end скрипт загрузки файла
index.php – главная страницы
js/upload.js – front-end скрипты главной страницы
Кроме того, необходим любой файл с картинкой для кнопки buttons/openfile.png
Загружаемые файлы помещаем в директорию ../temp/
.navButtons{
border:1px gray solid;
position:absolute;
overflow: hidden;
display:block;
height:50px;
width:50px;
margin:10px;
-moz-box-shadow:5px 5px 7px rgba(3,33,33,.7);
-webkit-box-shadow: 5px 5px 7px rgba(3,33,33,.7);
box-shadow: 5px 5px 7px rgba(3,33,33,.7);
-moz-border-radius:4px;
-webkit-border-radius:4px;
border-radius:4px;
}
.navButtons:hover
{
border:2px solid black;
background-color:#fff;
}
.hiddenInput{
position:absolute;
overflow: hidden;
display:block;
height:0px;
width:0px;
}
Input мы просто делаем нулевой ширины и высоты
<?php
// определяем callback функцию основного окна которой вернем ответ по окончанию загрузки
function jsOnResponse($obj)
{
echo '<script type="text/javascript"> window.parent.onResponse("'.$obj.'"); </script> ';
}
// определяем куда скопируем файл пользователя
$dir = '../temp/';
$name = basename($_FILES['loadfile']['name']);
$file = $dir . $name;
//копируем файл и получаем результат
$success = move_uploaded_file($_FILES['loadfile']['tmp_name'], $file);
//вызываем callback функцию и передаем ей результат
jsOnResponse("{'filename':'" . $name . "', 'success':'" . $success . "'}");
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="content-type" content="text/html; charset=windows-1251" />
<title>OpenFile test</title>
<link rel="stylesheet" href="css/style.css" type="text/css" media="screen, projection" />
</head>
<body>
<!-- Рисуем нашу кнопку, определяем ей реакцию на нажатие кнопки мыши -->
<div class="navButtons" onclick="FindFile();" title="Загрузка файла"><img src="buttons/openfile.png" width=100% height=100%/></a></div>
<!-- Делаем форму -->
<form action="view/upload.php" target="rFrame" method="POST" enctype="multipart/form-data">
<!-- Формируем спрятанные элементы -->
<div class="hiddenInput">
<input type="file" id="my_hidden_file" accept="image/jpeg,image/png,image/gif" name="loadfile" onchange="LoadFile();">
<input type="submit" id="my_hidden_load" style="display: none" value='Загрузить'>
</div></form>
<!-- И скрытый iframe таргет -->
<iframe id="rFrame" name="rFrame" style="display: none"> </iframe>
<!-- Подключаем скрипты -->
<script src="js/upload.js"> </script>
function FindFile() { document.getElementById('my_hidden_file').click(); }
function LoadFile() { document.getElementById('my_hidden_load').click(); }
function onResponse(d) // Функция обработки ответа от сервера
{
eval('var obj = ' + d + ';');
if(obj.success!=1)
{
alert('Ошибка!nФайл ' + obj.filename + " не загружен - "+obj.myres);
return;
};
alert('Файл загружен');
}
Автор: DyukhaIrkutsk