Как установить значение ввода файла при перетаскивании файла на страницу?
Я пытаюсь создать элемент управления, в котором вы можете одновременно выбрать файл для отправки в форме и вставить в него файл, чтобы сделать то же самое. У меня есть что-то вроде этого, где он также покажет предварительный просмотр файла, если это изображение:
<div class="preview-image-container">
<input type="file" name="File" id="File" accept="image/*"
class="image-url form-control" style="display:none;" />
<div class="preview-image-dummy"></div><img class="preview-image-url" />
<div class="preview-image-instruction">
<div class="preview-image-btn-browse btn btn-primary">Select file</div>
<p>or drop it here.</p>
</div>
</div>
Пользователь сбрасывает файл в preview-image-container
, Файл не отправлен с AJAX, пользователь должен отправить форму, которая содержит больше данных.
Из соображений безопасности нам не разрешено изменять значение входного файла с помощью JavaScript. Тем не менее, я знаю, что входной файл по умолчанию поддерживает возможность сброса, и есть множество сайтов, которые позволяют нам выбирать файлы, отбрасывая их в форме, поэтому я предполагаю, что есть способ сделать это.
Как вы можете видеть из MCVE, меня интересует только использование jQuery или чистого JavaScript без дополнительных библиотек.
Хотя можно использовать dropzone.js, он не подходит под мои требования и потребует значительного времени для настройки его внешнего вида. Кроме того, у dropzone.js есть определенные требования к конфигурации, которые не могут быть выполнены в моем приложении ASP.NET.
Есть похожий вопрос, но нет правильного ответа:
Как установить объект файла во входной файл в форме в HTML?
Также не похоже на перетаскивание входного файла и предварительный просмотр изображений перед загрузкой, потому что я уже выполнил действие перетаскивания и предварительного просмотра. Мой вопрос относится к проблеме наличия пустого файла ввода при отбрасывании файла в родительском контейнере.
1 ответ
Отказ от ответственности: Исправлено по состоянию на декабрь 2017 года и только для современных браузеров.
TL; DR: да, теперь вы можете!
* если у вас есть объект dataTransfer или FileList
Ранее программно меняли файлы input[type=file]
поле было отключено из-за устаревших уязвимостей, которые исправлены в современных браузерах.
Последний из основных браузеров (Firefox) недавно позволил нам установить файлы для поля входного файла. Согласно тестированию W3C, вы уже можете делать это в Google Chrome!
Соответствующий скриншот и текст цитаты из MDN:
Вы можете установить, а также получить значение
HTMLInputElement.files
во всех современных браузерах.
Совместимость источника и браузера, см. MDN
В ветке обсуждения исправления Firefox есть демо, на котором вы можете проверить его, и вот источник, если вы хотите отредактировать его. Для дальнейшего использования в случае утери этой ссылки я также включу ее в качестве исполняемого фрагмента ниже:
let target = document.documentElement;
let body = document.body;
let fileInput = document.querySelector('input');
target.addEventListener('dragover', (e) => {
e.preventDefault();
body.classList.add('dragging');
});
target.addEventListener('dragleave', () => {
body.classList.remove('dragging');
});
target.addEventListener('drop', (e) => {
e.preventDefault();
body.classList.remove('dragging');
fileInput.files = e.dataTransfer.files;
});
body {
font-family: Roboto, sans-serif;
}
body.dragging::before {
content: "Drop the file(s) anywhere on this page";
position: fixed;
left: 0; width: 100%;
top: 0; height: 100%;
display: flex;
justify-content: center;
align-items: center;
font-size: 1.5em;
background-color: rgba(255, 255, 0, .3);
pointer-events: none;
}
button, input {
font-family: inherit;
}
a {
color: blue;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width">
<link href="https://fonts.googleapis.com/css?family=Roboto:400,400i,700" rel="stylesheet">
<title>JS Bin</title>
</head>
<body>
<h1>Drag and drop files into file input</h1>
<p><small>Supported in <a href="https://github.com/whatwg/html/issues/2861">WebKit and Blink</a>. To test, drag and drop one or more files from your operating system onto this page.</small></p>
<p>
<input type="file">
</p>
</body>
</html>
Важная заметка:
Вы можете сделать это, только если у вас есть существующий
FileList
ИЛИ ЖЕdataTransfer
объект, который вы можете установить для элемента входного файла (так как метод установки НЕ принимает строки простого текста).Для получения дополнительной информации см. Ответ Kaiido здесь: Как установить объекты File и свойство length в объекте FileList, где файлы также отражаются в объекте FormData?
Теперь, чтобы ответить на ваш оригинальный вопрос, это должно быть так просто:
document.querySelector('.preview-image-instruction')
.addEventListener('drop', (ev) => {
ev.preventDefault();
document.querySelector('.image-url').files = ev.dataTransfer.files;
});