将拖放文件拖放到标准 html 文件输入中

如今,我们可以将文件拖放到一个特殊的容器中,并使用XHR 2上传它们。一次很多。具有实时进度条等。非常酷的东西。示例如下。

但有时我们不希望有那么多的凉爽。我想要的是将文件(一次多个)拖放到标准的HTML文件输入中:。<input type=file multiple>

这可能吗?有没有办法用文件删除中的正确文件名(?)“填充”文件输入?(出于文件系统安全原因,完整的文件路径不可用。

为什么?因为我想提交一个普通的表格。适用于所有浏览器和所有设备。拖放只是逐步增强,以增强和简化UX。具有标准文件输入(+属性)的标准表单将在那里。我想添加 HTML5 增强功能。multiple

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


答案 1

以下内容适用于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>

您可能希望使用 或 jQuery(等)来注册您的 evt 处理程序 - 这只是为了简洁起见。addEventListener


答案 2

我为此做了一个解决方案。

$(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;文件输入仅可见,因此您可以看到正在发生的事情。