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

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

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

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

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


当前回答

以下工作在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处理程序——这只是为了简洁起见。

其他回答

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

简单明了。您不需要创建一个新的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;">

使用它吧。(Html - Css);)

<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1">    
<style>
    .upload-container {
        position: relative;
    }
    .upload-container input {
        border: 1px solid #92b0b3;
        background: #f1f1f1;
        outline: 2px dashed #92b0b3;
        outline-offset: -10px;
        padding: 100px 0px 100px 250px;
        text-align: center !important;
        width: 500px;
    }
    .upload-container input:hover {
        background: #ddd;
    }   
    .upload-container:before {
        position: absolute;
        bottom: 50px;
        left: 245px;
        content: " (or) Drag and Drop files here. ";
        color: #3f8188;
        font-weight: 900;
    }   
    .upload-btn {
        margin-left: 300px;
        padding: 7px 20px;
    }        
</style>
<script>
             
    function uploadFiles() {
        var files = document.getElementById('file_upload').files;
        if(files.length==0){
            alert("Please first choose or drop any file(s)...");
            return;
        }
        var filenames="";
        for(var i=0;i<files.length;i++){
            filenames+=files[i].name+"\n";
        }
    }
            
</script>
</head>
<body>
    <div class="upload-container">
        <input type="file" id="file_upload" multiple />
    </div>
    <br>
    <button class="upload-btn" onclick="uploadFiles()">Submit</button>  
</body>
</html>

这是对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>

理论上,您可以添加一个覆盖<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中已经可以在输入中删除多个文件。