现在我们可以把文件拖放到一个特殊的容器中,然后用XHR 2上传。一次很多。实时进度条等。非常酷的东西。例子。
但有时候我们并不想要那么酷。我想要的是拖放文件—许多一次—到一个标准的HTML文件输入:<input type=file multiple>。
这可能吗?是否有一些方法来“填充”文件输入与正确的文件名(?)从文件掉落?(出于文件系统安全原因,不能使用完整的文件路径。)
为什么?因为我想提交一份正常的表格。适用于所有浏览器和所有设备。拖放只是为了增强和简化用户体验的渐进式增强。带有标准文件输入(+多个属性)的标准表单将出现在那里。我想增加HTML5的增强功能。
编辑
我知道在某些浏览器中,有时(几乎总是)可以将文件放入文件输入本身。我知道Chrome通常会这样做,但有时它会失败,然后在当前页面加载文件(如果你正在填写表单,这是一个大失败)。我想愚弄&防浏览器。
理论上,您可以添加一个覆盖<input/>的元素,然后使用它的drop事件来捕获文件(使用File API)并将它们传递给输入文件数组。
除了文件输入是只读的。这是一个老问题。
然而,你可以完全绕过表单控件,通过XHR上传(不确定是否支持):
https://developer.mozilla.org/en/Using_files_from_web_applications
http://www.html5rocks.com/en/tutorials/file/xhr2/#toc-send-blob
你也可以在周围区域使用一个元素来取消Chrome中的删除事件,并防止默认的加载文件行为。
在Safari和Firefox中已经可以在输入中删除多个文件。
简单明了。您不需要创建一个新的FormData或执行Ajax来发送图像。您可以在输入字段中放置拖拽文件。
Osx用户:也许在Osx中你需要最大化你的浏览器来拖动文件。为什么?idk。
$dropzone.ondrop = function (e) {
e.preventDefault();
input.files = e.dataTransfer.files;
}
var $dropzone = document.querySelector('.dropzone');
var input = document.getElementById('file-upload');
$dropzone.ondragover = function (e) {
e.preventDefault();
this.classList.add('dragover');
};
$dropzone.ondragleave = function (e) {
e.preventDefault();
this.classList.remove('dragover');
};
$dropzone.ondrop = function (e) {
e.preventDefault();
this.classList.remove('dragover');
input.files = e.dataTransfer.files;
}
.dropzone {
padding: 10px;
border: 1px dashed black;
}
.dropzone.dragover {
background-color: rgba(0, 0, 0, .3);
}
<div class="dropzone">Drop here</div>
<input type="file" id="file-upload" style="display:none;">
这是“DTHML”HTML5的实现方式。标准表单输入(正如Ricardo Tomasi指出的那样,只能读取)。然后,如果拖入一个文件,它就会附加到表单上。这将需要修改操作页面,以接受以这种方式上传的文件。
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>
如果你能把整个窗口变成一个拖放区,那就更boss了,看看我如何检测进入和离开窗口的HTML5拖放事件,就像Gmail一样?
这是对William Entriken给出的例子的改进、修正和修改。有一些问题。例如,<input type="file" />的正常按钮没有做任何事情(以防用户想要以这种方式上传文件)。
注意:我正在制作一个只有我自己使用的web应用程序,所以这只针对Firefox进行了测试(和改进)。我确信,即使您开发跨浏览器的情况下,这些代码也是有价值的。
function readFile(e) {
var files;
if (e.target.files) {
files=e.target.files
} else {
files=e.dataTransfer.files
}
if (files.length==0) {
alert('What you dropped is not a file.');
return;
}
var file=files[0];
document.getElementById('fileDragName').value = file.name
document.getElementById('fileDragSize').value = file.size
document.getElementById('fileDragType').value = file.type
reader = new FileReader();
reader.onload = function(e) {
document.getElementById('fileDragData').value = e.target.result;
}
reader.readAsDataURL(file);
}
function getTheFile(e) {
e.target.style.borderColor='#ccc';
readFile(e);
}
<input type="file" onchange="readFile(event)">
<input id="fileDragName">
<input id="fileDragSize">
<input id="fileDragType">
<input id="fileDragData">
<div style="width:200px; height:200px; border: 10px dashed #ccc"
ondragover="this.style.borderColor='#0c0';return false;"
ondragleave="this.style.borderColor='#ccc'"
ondrop="getTheFile(event); return false;"
></div>
对于那些想在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-value跨度吗?这就是我们打印文件名的地方。
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;
}
});
就是这样。