Перейти к содержимому

Как получить файл из input type file

  • автор:

Как стилизовать поле для отправки файла

Привет, друзья. Давно просят сделать статью о том, как стилизовать input с type file, то есть поле для прикрепления файла. Однажды, косвенно я затрагивал эту тему в одной из статей, но сегодня мы остановимся на ней подробнее.

Конечно, как обычно есть несколько путей решить эту задачу. Это:

  • Использовать фреймворк, такой как Bootstrap, Foundation и подобные.
  • Попробовать самостоятельно стилизовать при помощи JS и CSS.
  • Воспользоваться плагином для стилизации поля с типом «file».

Стилизация поля input с типом file

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

Остается попробовать самостоятельно привести все в порядок или воспользоваться плагином. Давайте остановимся на этих 2 вариантах подробнее, чтобы у вас больше не возникало вопросов как всё-таки стилизовать тег input с атрибутом type=file. Я подробно опишу вариант самостоятельной стилизации, а в конце дам ссылку на плагин, который делает практически тоже самое.

Самостоятельная стилизация тега input с типом «файл»

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

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

Итак, обычно я оборачиваю все инпуты и элементы, которые относятся к ним в общий контейнер. Мне так удобней, легче верстать, позиционировать и стилизовать.

Как я уже и говорил, мы будем отслеживать клик по label, который связан с инпутом, при этом само поле, которое предназначено для отправки файла мы скроем, задав ему прозрачность «0».

 

Вот так сейчас выглядит поле в браузере:

Добавим стили, чтобы получить описываемый результат. То есть скроем input, оставим только label, поместим в него иконку и сделаем его похожим на обычную кнопку, но сначала, добавим кое-что в верстку:

Теперь добавим стили:

.input__wrapper < width: 100%; position: relative; margin: 15px 0; text-align: center; >.input__file < opacity: 0; visibility: hidden; position: absolute; >.input__file-icon-wrapper < height: 60px; width: 60px; margin-right: 15px; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -webkit-box-pack: center; -ms-flex-pack: center; justify-content: center; border-right: 1px solid #fff; >.input__file-button-text < line-height: 1; margin-top: 1px; >.input__file-button

Вот что получилось:

Как видите, уже лучше, но пока мы не видим никакой реакции на то, что файл выбран. Нет никакого уведомления и никакой индикации. Давайте исправим это. Под формой, ближе к закрывающему тегу body добавьте следующий скрипт:

  

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

Для примера добавил сразу 2 поля, чтобы продемонстрировать что это работает и в случае, если у вас несколько форм или полей.

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

.field__wrapper < width: 100%; position: relative; margin: 15px 0; text-align: center; >.field__file < opacity: 0; visibility: hidden; position: absolute; >.field__file-wrapper < width: 100%; display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-pack: justify; -ms-flex-pack: justify; justify-content: space-between; -webkit-box-align: center; -ms-flex-align: center; align-items: center; -ms-flex-wrap: wrap; flex-wrap: wrap; >.field__file-fake < height: 60px; width: calc(100% - 130px); display: -webkit-box; display: -ms-flexbox; display: flex; -webkit-box-align: center; -ms-flex-align: center; align-items: center; padding: 0 15px; border: 1px solid #c7c7c7; border-radius: 3px 0 0 3px; border-right: none; >.field__file-button

  

Как видите, все не очень сложно, плюс, без jQuery, так что если у вас она уже не используется, то можно не тянуть ее за собой, ради такого скромного функционала.

Стилизация «input type file» при помощи плагина

Теперь давайте рассмотрим вариант стилизация поля для отправки файла при помощи jQuery плагина. Называется он jQuery Fileinput. Как я уже говорил, делает он практически тоже самое, просто автоматически.

Для настройки сначала подключаем сам плагин и jQuery:

Затем создаем input:

И инициализируете плагин:

  

После инициализации сам инпут скроется, а на его месте появится кнопка.

Чтобы задать ей свой класс и поместить в нее свой текст, нужно передать в fileinput html. Например так:

  

Для наглядности, смотрите пример на jsfiddle, а на сегодня все. Надеюсь, что у вас больше не осталось вопросов по поводу того, как стилизовать input с type fifle.

05/10/2022 Дмитрий Давыдов

Похожие публикации

  • Атрибут accept в input type file
  • Как получить адрес страницы с которой отправлена форма
  • Атрибут type тега input. Повышаем usability

13 комментариев

Годнота, спасибо, я просто делал всегда рамку вокруг инпута и центрировал его. Вообще есть много споров по поводу того, стоит ли индивидуализировать этот и другие элементы, или оставить так, как многие уже привыкли, то есть по умолчанию и одинаково +- во всех браузерах.

Здравствуйте. Не работает смена текста и вывод подсчитанных файлов в связке с плагином multifile-upload-field-for-contact-form-7 — может есть предположения как это можно исправить?

Что делает multifile-upload-field-for-contact-form-7? Если просто добавляет enctype=’multipart/form-data’, то попробуйте добавить этот параметр скриптом обычным, а не плагином.

Отличная стилизация Input. Давно искал такой вариант дизайна. Но при попытке передать файл на сервер, у меня появилась ошибка «Не удалось открыть поток: отказано в доступе». Что я сделал?
Я загуглил эту тему и вот что нашел. Может кому то пригодиться.
1. Узнайте код ошибки php. Поместите этот код в начало файла php.

ini_set('error_reporting', E_ALL); ini_set('display_errors', 1); ini_set('display_startup_errors', 1);

2. К папке должен быть доступ 777. Проверь это.
3. Тег form должен иметь атрибут enctype = «multipart/form-data» method = «post». 4. Полностью открой и посмотри массив $ _FILES на сервере.

print_r($_FILES);

5. Открой и посмотри массив $ _FILES на клиенте.

file = document.getElementById("get_avatar").files[0];parts = file.name.split('.'); var a = file.size;var b = parts.pop();var c = file.type;alert(a+b+c);

6. Проверь права пользователя и группы пользователей на каталог.

cd /var/www/your_site/user ls -l

Подробнее: __http://profi.spage.me/php/check-file-input-on-php-and-jquery-why-error
Дмитрий Давыдов

Aleksey, спасибо, что не оставили без внимания и дали такой развернутый ответ. Кому-то обязательно пригодится!

Доброго времени суток. Оформил по данному примеру кнопку отправки.
Прошу прощения за, может быть, тупой вопрос, но.
Как получить вложенные файлы на почту? Если с остальными полями понятно
[tel* tel-136] выведет телефон который введет пользователь и т.д.
Но что в данном случае вставить в поле «Прикрепленные файлы», чтобы файл пришел на почту?
Еще раз прошу прощения, за может быть примитивный вопрос.

Добрый день sn_eg, несколько я понял, вы хотите отправить email с вложением. При помощи input file мы получаем файл от пользователя и загружаем его к себе на сервер в папку. Выше есть код. А что бы отправить email с этим файлом из этой папки с сервера, надо делать php код отправки email с вложенным файлом. Вот здесь есть пример: http://www.php.su/articles/?cat=examples&page=060
Если вы делаете отправку email с сервера первый раз. То разберите сперва пример попроще. PHP отправка email с сервера (загуглите пример). А затем если получится, email с вложением.

Я впервые сталкиваюсь вообще с отправкой файлов с формы. Все сделал по инструкции с поста, но так и не понял в какой папке хранятся файлы отправленные с формы cf7. На самом деле, проблема была только в стилизации кнопки отправки файлов, но более разумного решение, чем тут, не нашел. И стилизовал так как нужно, но столкнулся с рядом вопросов, с которыми ранее не сталкивался. В какую папку сохраняются файлы? Где их можно найти? Тыкните носом, пожалуйста.

Я понял вас, здесь нет кода. Код этого примера, вот здесь: https://profi.spage.me/php/check-file-input-on-php-and-jquery-why-error/
Там есть такие строчки:
$name_file_avatar = $_FILES[‘myfile’][‘name’];
////—-еще код—-///
$tmp_dir = $_FILES[‘myfile’][‘tmp_name’];
$destiation_dir = ‘/var/www/spage.me/html/user/download/’.$name_file_avatar;
move_uploaded_file($tmp_dir, $destiation_dir ); 1.Узнаем имя файла.
2.Берем сам файл.
3.Путь (папка) на сервере куда будет скопирован файл.
4.Перемещаем файл с браузера на сервер. Если есть трудности, напишите мне пожалуйста в VK https://vk.com/alekseyvanin
Я чем смогу, помогу!

Спасибо большое. Как доберусь до ноута, посмотрю/попробую.

Здравствуйте. подскажите на счет ошибки. у меня скрипт добавлен к форме с валидацией. сначала отработало, потом стало ошибку выдавать Uncaught TypeError: Cannot read properties of null (reading ‘innerText’) и ругается на forEach.
в сайт после добавление вносились правки. но совсем мелкие. типа на jquery парочка классов была навешана. и хз чего перестало отрабатывать. вроде все осталось как было

Здравствуйте, сложно ответить как решить эту проблему, мало данных. Надо смотреть на сайте, в консоле отладки кода. Желательно ещё иметь доступ к папке сайта, что бы править код. Если хотите, скажу своему помощнику он отладит код.

Алексей, Спасибо за быстрый ответ. В результате долгий тыканий удалось найти проблему. Она была в параметре nextElementSibling. Поскольку параметр отвечает за выборку предыдущего элемента формы, пошел косяк. В форме просто добавили доп поле с текстом.

File и FileReader

Объект File наследуется от объекта Blob и обладает возможностями по взаимодействию с файловой системой.

Есть два способа его получить.

Во-первых, есть конструктор, похожий на Blob :

new File(fileParts, fileName, [options])
  • fileParts – массив значений Blob / BufferSource /строки.
  • fileName – имя файла, строка.
  • options – необязательный объект со свойством:
    • lastModified – дата последнего изменения в формате таймстамп (целое число).

    Во-вторых, чаще всего мы получаем файл из или через перетаскивание с помощью мыши, или из других интерфейсов браузера. В этом случае файл получает эту информацию из ОС.

    Так как File наследует от Blob , у объектов File есть те же свойства плюс:

    • name – имя файла,
    • lastModified – таймстамп для даты последнего изменения.

    В этом примере мы получаем объект File из :

       

    На заметку:

    Через можно выбрать несколько файлов, поэтому input.files – псевдомассив выбранных файлов. Здесь у нас только один файл, поэтому мы просто берём input.files[0] .

    FileReader

    FileReader объект, цель которого читать данные из Blob (и, следовательно, из File тоже).

    Данные передаются при помощи событий, так как чтение с диска может занять время.

    let reader = new FileReader(); // без аргументов
    • readAsArrayBuffer(blob) – считать данные как ArrayBuffer
    • readAsText(blob, [encoding]) – считать данные как строку (кодировка по умолчанию: utf-8 )
    • readAsDataURL(blob) – считать данные как base64-кодированный URL.
    • abort() – отменить операцию.

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

    • readAsArrayBuffer – для бинарных файлов, для низкоуровневой побайтовой работы с бинарными данными. Для высокоуровневых операций у File есть свои методы, унаследованные от Blob , например, slice , мы можем вызвать их напрямую.
    • readAsText – для текстовых файлов, когда мы хотим получить строку.
    • readAsDataURL – когда мы хотим использовать данные в src для img или другого тега. Есть альтернатива – можно не читать файл, а вызвать URL.createObjectURL(file) , детали в главе Blob.

    В процессе чтения происходят следующие события:

    • loadstart – чтение начато.
    • progress – срабатывает во время чтения данных.
    • load – нет ошибок, чтение окончено.
    • abort – вызван abort() .
    • error – произошла ошибка.
    • loadend – чтение завершено (успешно или нет).

    Когда чтение закончено, мы сможем получить доступ к его результату следующим образом:

    • reader.result результат чтения (если оно успешно)
    • reader.error объект ошибки (при неудаче).

    Наиболее часто используемые события – это, конечно же, load и error .

    Вот пример чтения файла:

       

    FileReader для Blob

    Как упоминалось в главе Blob, FileReader работает для любых объектов Blob, а не только для файлов.

    Поэтому мы можем использовать его для преобразования Blob в другой формат:

    • readAsArrayBuffer(blob) – в ArrayBuffer ,
    • readAsText(blob, [encoding]) – в строку (альтернатива TextDecoder ),
    • readAsDataURL(blob) – в формат base64-кодированного URL.

    Для Web Worker также доступен FileReaderSync

    Для веб-воркеров доступен синхронный вариант FileReader , именуемый FileReaderSync.

    Его методы считывания read* не генерируют события, а возвращают результат, как это делают обычные функции.

    Но это только внутри веб-воркера, поскольку задержки в синхронных вызовах, которые возможны при чтении из файла, в веб-воркерах менее важны. Они не влияют на страницу.

    Итого

    File объекты наследуют от Blob .

    Помимо методов и свойств Blob , объекты File также имеют свойства name и lastModified плюс внутреннюю возможность чтения из файловой системы. Обычно мы получаем объекты File из пользовательского ввода, например, через или перетаскиванием с помощью мыши, в событии dragend .

    Объекты FileReader могут читать из файла или Blob в одном из трёх форматов:

    • Строка ( readAsText ).
    • ArrayBuffer ( readAsArrayBuffer ).
    • URL в формате base64 ( readAsDataURL ).

    Однако, во многих случаях нам не нужно читать содержимое файла. Как и в случае с Blob, мы можем создать короткий URL с помощью URL.createObjectURL(file) и использовать его в теге или . Таким образом, файл может быть загружен или показан в виде изображения, как часть canvas и т.д.

    А если мы собираемся отправить File по сети, то это также легко, поскольку в сетевые методы, такие как XMLHttpRequest или fetch , встроена возможность отсылки File .

    Как получить путь к файлу из input type=»file»?

    Rsa97

    IMHO, никак. Доступ к реальной файловой системе из js-скрипта в браузере сильно ограничен. Максимум — получить реальное имя без полного пути и временное служебное имя вида blob:null/8d02a1cb-72bc-4026-a4f7-d5f1c5d08bce.

    P.S. Странное имя функции «добавить неудачу».

    Ответ написан более года назад
    Комментировать
    Нравится 1 Комментировать
    Stalker_RED @Stalker_RED

    Вы можете получить имя файла из input.value.

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

    Ответ написан более года назад
    Комментировать
    Нравится 1 Комментировать
    Ответы на вопрос 1
    Софт для автоматизации

    Пути получить можно, но только если выбирается папка.

    Например, введите в консоли:

    var input = document.createElement('input'); input.setAttribute('type', 'file'); input.setAttribute('webkitdirectory', 'true'); input.addEventListener('change', function() < console.log('Выбраны файлы', input.files); console.log('Пути файлов относительно выбранной папки:'); for (var n = 0; n < input.files.length; n++) < console.log(input.files[n].webkitRelativePath); >>); input.click();

    И выберите какую-нибудь папку, где будет хотя бы несколько файлов (любых).

    Также при большом желании можно получить путь в виде Data URL — это такой формат адреса, когда файл сам весь целиком помещается непосредственно в адрес (в ссылку). Ниже пример Data URL, попробуйте его открыть:

    data:image/png;base64,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

    Как получить Blob из input[type=»files»]?

    Однако, для этого мне сначала нужно получить «на руки» Blob.
    Подскажите, как можно вытащить Blob из поля input со вставленным файлом?

    • Вопрос задан более трёх лет назад
    • 746 просмотров

    Комментировать

    Решения вопроса 1

    bingo347

    Дмитрий Беляев @bingo347 Куратор тега JavaScript

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *