现在我们可以把文件拖放到一个特殊的容器中,然后用XHR 2上传。一次很多。实时进度条等。非常酷的东西。例子。

但有时候我们并不想要那么酷。我想要的是拖放文件—许多一次—到一个标准的HTML文件输入:<input type=file multiple>。

这可能吗?是否有一些方法来“填充”文件输入与正确的文件名(?)从文件掉落?(出于文件系统安全原因,不能使用完整的文件路径。)

为什么?因为我想提交一份正常的表格。适用于所有浏览器和所有设备。拖放只是为了增强和简化用户体验的渐进式增强。带有标准文件输入(+多个属性)的标准表单将出现在那里。我想增加HTML5的增强功能。

编辑 我知道在某些浏览器中,有时(几乎总是)可以将文件放入文件输入本身。我知道Chrome通常会这样做,但有时它会失败,然后在当前页面加载文件(如果你正在填写表单,这是一个大失败)。我想愚弄&防浏览器。


当前回答

对于那些想在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;
    }
});

就是这样。

其他回答

这是“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一样?

以下工作在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; // If you want to use some of the dropped files const dT = new DataTransfer(); dT.items.add(evt.dataTransfer.files[0]); dT.items.add(evt.dataTransfer.files[3]); fileInput.files = dT.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处理程序——这只是为了简洁起见。

对于那些想在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;
    }
});

就是这样。

几年后,我已经构建了这个库来将文件放入任何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();

对于没有任何JS的本地解决方案:

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

<style>
    .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;
    }
</style>

改编自https://codepen.io/Scribblerockerz/pen/qdWzJw