Полностью своя кнопка «Выбрать файл»

в 10:25, , рубрики: ajax, javascript, JS, php

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

Предлагаю на суд сообщества свой велосипед. На написание данного текста вдохновил Способ №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/

Таблица стилей (css/style.css)

Создаем стиль кнопки и скрытого «input».

.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 мы просто делаем нулевой ширины и высоты

Скрипт обрабатывающий запрос на загрузку файла (view/upload.php)

Здесь все согласно примерам в интернете, валидация файлов изъята:

<?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 . "'}");  
?> 

Главная страница (index.php)

<!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>

JavaScript в главной форме (js/upload.js)

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

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js