В эти дни мы можем перетаскивать файлы в специальный контейнер и загружать их с XHR 2. Многие за раз. С живыми индикаторами прогресса и т.д. Очень классный материал. Пример здесь.
Но иногда мы не хотим такой прохлады. Я бы хотел перетащить файлы - много за раз - в стандартный входной файл HTML: <input type=file multiple>
.
Это возможно? Есть ли способ "заполнить" ввод файла правильными именами файлов (?) Из файла? (Полный путь к файлу недоступен по соображениям безопасности файловой системы.)
Почему? Потому что я хотел бы подать обычную форму. Для всех браузеров и всех устройств. Перетаскивание - это просто прогрессивное усовершенствование для улучшения и упрощения UX. Там будет стандартная форма со стандартным вводом файла (+ multiple
). Я хотел бы добавить усовершенствование HTML5.
изменить
Я знаю, что в некоторых браузерах вы можете иногда (почти всегда) отбрасывать файлы в сам файл. Я знаю, что Chrome обычно делает это, но иногда он терпит неудачу, а затем загружает файл на текущей странице (большой сбой, если вы заполняете форму). Я хочу обмануть и защитить его от браузера.
Я сделал для этого решение.
$(function () {
var dropZoneId = "drop-zone";
var buttonId = "clickHere";
var mouseOverClass = "mouse-over";
var dropZone = $("#" + dropZoneId);
var ooleft = dropZone.offset().left;
var ooright = dropZone.outerWidth() + ooleft;
var ootop = dropZone.offset().top;
var oobottom = dropZone.outerHeight() + ootop;
var inputFile = dropZone.find("input");
document.getElementById(dropZoneId).addEventListener("dragover", function (e) {
e.preventDefault();
e.stopPropagation();
dropZone.addClass(mouseOverClass);
var x = e.pageX;
var y = e.pageY;
if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
inputFile.offset({ top: y - 15, left: x - 100 });
} else {
inputFile.offset({ top: -400, left: -400 });
}
}, true);
if (buttonId != "") {
var clickZone = $("#" + buttonId);
var oleft = clickZone.offset().left;
var oright = clickZone.outerWidth() + oleft;
var otop = clickZone.offset().top;
var obottom = clickZone.outerHeight() + otop;
$("#" + buttonId).mousemove(function (e) {
var x = e.pageX;
var y = e.pageY;
if (!(x < oleft || x > oright || y < otop || y > obottom)) {
inputFile.offset({ top: y - 15, left: x - 160 });
} else {
inputFile.offset({ top: -400, left: -400 });
}
});
}
document.getElementById(dropZoneId).addEventListener("drop", function (e) {
$("#" + dropZoneId).removeClass(mouseOverClass);
}, true);
})
#drop-zone {
/*Sort of important*/
width: 300px;
/*Sort of important*/
height: 200px;
position:absolute;
left:50%;
top:100px;
margin-left:-150px;
border: 2px dashed rgba(0,0,0,.3);
border-radius: 20px;
font-family: Arial;
text-align: center;
position: relative;
line-height: 180px;
font-size: 20px;
color: rgba(0,0,0,.3);
}
#drop-zone input {
/*Important*/
position: absolute;
/*Important*/
cursor: pointer;
left: 0px;
top: 0px;
/*Important This is only comment out for demonstration purposes.
opacity:0; */
}
/*Important*/
#drop-zone.mouse-over {
border: 2px dashed rgba(0,0,0,.5);
color: rgba(0,0,0,.5);
}
/*If you dont want the button*/
#clickHere {
position: absolute;
cursor: pointer;
left: 50%;
top: 50%;
margin-left: -50px;
margin-top: 20px;
line-height: 26px;
color: white;
font-size: 12px;
width: 100px;
height: 26px;
border-radius: 4px;
background-color: #3b85c3;
}
#clickHere:hover {
background-color: #4499DD;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="drop-zone">
Drop files here...
<div id="clickHere">
or click here..
<input type="file" name="file" id="file" />
</div>
</div>
Функция перетаскивания для этого метода работает только с Chrome, Firefox и Safari. (Не знаю, работает ли он с IE10), но для других браузеров кнопка "Или нажмите здесь" работает нормально.
Поле ввода просто следует за мышью при перетаскивании файла по области, и я добавил также кнопку.
Несогласованность непрозрачности: 0; вход файла отображается только, чтобы вы могли видеть, что происходит.
В Chrome и FF работает следующее, но мне еще предстоит найти решение, которое также охватывает IE10 +:
// dragover and dragenter events need to have 'preventDefault' called
// in order for the 'drop' event to register.
// See: https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Drag_operations#droptargets
dropContainer.ondragover = dropContainer.ondragenter = function(evt) {
evt.preventDefault();
};
dropContainer.ondrop = function(evt) {
// pretty simple -- but not for IE :(
fileInput.files = evt.dataTransfer.files;
evt.preventDefault();
};
<!DOCTYPE html>
<html>
<body>
<div id="dropContainer" style="border:1px solid black;height:100px;">
Drop Here
</div>
Should update here:
<input type="file" id="fileInput" />
</body>
</html>
Вероятно, вы захотите использовать addEventListener
или jQuery (и т.д.) для регистрации ваших обработчиков evt - это просто ради краткости.
MSIE
, Trident/
(IE11) и Edge/
(IE12) ...
Это способ HTML5 "DTHML". Нормальный ввод формы (который читается только, как указал Рикардо Томаси). Затем, если файл перетаскивается, он привязан к форме. Это WILL требует изменения страницы действия, чтобы принять файл, загруженный таким образом.
function readfiles(files) {
for (var i = 0; i < files.length; i++) {
document.getElementById('fileDragName').value = files[i].name
document.getElementById('fileDragSize').value = files[i].size
document.getElementById('fileDragType').value = files[i].type
reader = new FileReader();
reader.onload = function(event) {
document.getElementById('fileDragData').value = event.target.result;}
reader.readAsDataURL(files[i]);
}
}
var holder = document.getElementById('holder');
holder.ondragover = function () { this.className = 'hover'; return false; };
holder.ondragend = function () { this.className = ''; return false; };
holder.ondrop = function (e) {
this.className = '';
e.preventDefault();
readfiles(e.dataTransfer.files);
}
#holder.hover { border: 10px dashed #0c0 !important; }
<form method="post" action="http://example.com/">
<input type="file"><input id="fileDragName"><input id="fileDragSize"><input id="fileDragType"><input id="fileDragData">
<div id="holder" style="width:200px; height:200px; border: 10px dashed #ccc"></div>
</form>
Еще больше босса, если вы можете сделать все окно зоной выпадения, см. Как определить событие перетаскивания HTML5, входящее и выходящее из окна, например Gmail?
//----------App.js---------------------//
$(document).ready(function() {
var holder = document.getElementById('holder');
holder.ondragover = function () { this.className = 'hover'; return false; };
holder.ondrop = function (e) {
this.className = 'hidden';
e.preventDefault();
var file = e.dataTransfer.files[0];
var reader = new FileReader();
reader.onload = function (event) {
document.getElementById('image_droped').className='visible'
$('#image_droped').attr('src', event.target.result);
}
reader.readAsDataURL(file);
};
});
.holder_default {
width:500px;
height:180px;
border: 10px dashed #ccc;
}
#holder.hover {
width:400px;
height:180px;
border: 10px dashed #0c0 !important;
}
.hidden {
visibility: hidden;
}
.visible {
visibility: visible;
}
<!DOCTYPE html>
<html>
<head>
<title> HTML 5 </title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.js"></script>
</head>
<body>
<form method="post" action="http://example.com/">
<div id="holder" style="" id="holder" class="holder_default">
<img src="" id="image_droped" width="500" height="180" style="width:500px; height:180px; border: 10px dashed #7A97FC;" class=" hidden"/>
</div>
</form>
</body>
</html>
В теории вы можете добавить элемент, наложенный на <input/>
, а затем использовать его drop
для захвата файлов (используя File API) и передать их в массив files
.
За исключением того, что ввод файла только для чтения. Это старая проблема.
Однако вы можете полностью обходить элемент управления формой и загружать через XHR (не уверен в поддержке этого):
Вы также можете использовать элемент в окружении для отмены события переадресации в Chrome и предотвращения по умолчанию загрузки файла.
Отбрасывание нескольких файлов по вводу уже работает в Safari и Firefox.
Я знаю, что в Chrome работает трюк.
При отбрасывании файлов в зону перетаскивания вы получаете объект dataTransfer.files, который является объектом типа FileList, который содержит все файлы, которые вы перетаскивали. Между тем элемент имеет свойство "файлы", то есть тот же объект типа "FileList".
Итак, вы можете просто определить объект dataTransfer.files для свойства input.files.
input.files
не может = (
Для решения только CSS:
<div class="file-area">
<input type="file">
<div class="file-dummy">
<span class="default">Click to select a file, or drag it here</span>
<span class="success">Great, your file is selected</span>
</div>
</div>
.file-area {
width: 100%;
position: relative;
font-size: 18px;
}
.file-area input[type=file] {
position: absolute;
width: 100%;
height: 100%;
top: 0;
left: 0;
right: 0;
bottom: 0;
opacity: 0;
cursor: pointer;
}
.file-area .file-dummy {
width: 100%;
padding: 50px 30px;
border: 2px dashed #ccc;
background-color: #fff;
text-align: center;
transition: background 0.3s ease-in-out;
}
.file-area .file-dummy .success {
display: none;
}
.file-area:hover .file-dummy {
border: 2px dashed #1abc9c;
}
.file-area input[type=file]:valid + .file-dummy {
border-color: #1abc9c;
}
.file-area input[type=file]:valid + .file-dummy .success {
display: inline-block;
}
.file-area input[type=file]:valid + .file-dummy .default {
display: none;
}
Изменено из https://codepen.io/Scribblerockerz/pen/qdWzJw
Для тех, кто хочет сделать это в 2018 году, у меня есть намного лучшее и более простое решение, чем все старые вещи, размещенные здесь. Вы можете создать красивый перетаскивающий блок с простым HTML, JavaScript и CSS.
(Пока работает только в Chrome)
Давайте начнем с HTML.
<div>
<input type="file" name="file" id="file" class="file">
<span id="value"></span>
</div>
Тогда мы перейдем к стайлингу.
.file {
width: 400px;
height: 50px;
background: #171717;
padding: 4px;
border: 1px dashed #333;
position: relative;
cursor: pointer;
}
.file::before {
content: '';
position: absolute;
background: #171717;
font-size: 20px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
width: 100%;
height: 100%;
}
.file::after {
content: 'Drag & Drop';
position: absolute;
color: #808080;
font-size: 20px;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}
После того, как вы это сделали, все уже выглядит хорошо. Но я думаю, что вы хотели бы посмотреть, какой файл вы загрузили на самом деле, поэтому мы собираемся сделать немного JavaScript. Помните тот диапазон значений pfp? Вот где мы распечатаем имя файла.
let file = document.getElementById('file');
file.addEventListener('change', function() {
if(file && file.value) {
let val = file.files[0].name;
document.getElementById('value').innerHTML = "Selected" + val;
}
});
И это оно.
Несколько лет спустя я построил эту библиотеку для перетаскивания файлов в любой элемент HTML.
Вы можете использовать его как
const Droppable = require('droppable');
const droppable = new Droppable({
element: document.querySelector('#my-droppable-element')
})
droppable.onFilesDropped((files) => {
console.log('Files were dropped:', files);
});
// Clean up when you're done!
droppable.destroy();
Удивительная работа @BjarkeCK. Я внесла некоторые изменения в его работу, чтобы использовать его как метод в jquery:
$.fn.dropZone = function() {
var buttonId = "clickHere";
var mouseOverClass = "mouse-over";
var dropZone = this[0];
var $dropZone = $(dropZone);
var ooleft = $dropZone.offset().left;
var ooright = $dropZone.outerWidth() + ooleft;
var ootop = $dropZone.offset().top;
var oobottom = $dropZone.outerHeight() + ootop;
var inputFile = $dropZone.find("input[type='file']");
dropZone.addEventListener("dragleave", function() {
this.classList.remove(mouseOverClass);
});
dropZone.addEventListener("dragover", function(e) {
console.dir(e);
e.preventDefault();
e.stopPropagation();
this.classList.add(mouseOverClass);
var x = e.pageX;
var y = e.pageY;
if (!(x < ooleft || x > ooright || y < ootop || y > oobottom)) {
inputFile.offset({
top: y - 15,
left: x - 100
});
} else {
inputFile.offset({
top: -400,
left: -400
});
}
}, true);
dropZone.addEventListener("drop", function(e) {
this.classList.remove(mouseOverClass);
}, true);
}
$('#drop-zone').dropZone();
Это то, что я вышел.
Использование Jquery и Html. Это добавит его в файлы вставки.
var dropzone = $('#dropzone')
dropzone.on('drag dragstart dragend dragover dragenter dragleave drop', function(e) {
e.preventDefault();
e.stopPropagation();
})
dropzone.on('dragover dragenter', function() {
$(this).addClass('is-dragover');
})
dropzone.on('dragleave dragend drop', function() {
$(this).removeClass('is-dragover');
})
dropzone.on('drop',function(e) {
var files = e.originalEvent.dataTransfer.files;
// Now select your file upload field
// $('input_field_file').prop('files',files)
});
input { margin: 15px 10px !important;}
.dropzone {
padding: 50px;
border: 2px dashed #060;
}
.dropzone.is-dragover {
background-color: #e6ecef;
}
.dragover {
bg-color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/1.12.4/jquery.min.js"></script>
<div class="" draggable='true' style='padding: 20px'>
<div id='dropzone' class='dropzone'>
Drop Your File Here
</div>
</div>
Что вы можете сделать, это отобразить входной файл и наложить его на свою прозрачную область, осторожно использовать имя типа file[1]
. {Убедитесь, что в вашем теге FORM есть enctype = "multipart/form-data"
.}
Затем добавьте дескриптор дескриптора дополнительных файлов, динамически создав больше файлов для файлов 2..number_of_files, обязательно используйте одно и то же базовое имя, соответствующим образом заполнив атрибут value.
Наконец, (front-end) отправьте форму.
Все, что требуется для обработки этого метода, - это изменить вашу процедуру для обработки массива файлов.
multiple
атрибутов в наши дни. Нет необходимости вводить более 1 файла. Это не проблема, хотя. Как получить объекты File
в файл ввода? Я думаю, что это требует некоторого примера кода ...