wake-up-neo.com

ziehen Sie die Drop-Dateien in die Standardeingabe von HTML-Dateien

Heutzutage können wir Dateien per Drag & Drop in einen speziellen Container ziehen und sie mit XHR 2 hochladen. Viele gleichzeitig. Mit Live-Fortschrittsbalken usw. Sehr cooles Zeug. Beispiel hier.

Aber manchmal wollen wir nicht so viel Coolness. Ich möchte Dateien per Drag & Drop - viele gleichzeitig - in eine Standard-HTML-Dateieingabe: <input type=file multiple> ziehen.

Ist das möglich? Gibt es eine Möglichkeit, die Dateieingabe mit den richtigen Dateinamen (?) Aus dem Ablageordner zu "füllen"? (Aus Gründen der Dateisystemsicherheit sind keine vollständigen Dateipfade verfügbar.)

Warum? Weil ich ein normales Formular einreichen möchte. Für alle Browser und alle Geräte. Das Drag & Drop ist nur eine schrittweise Verbesserung, um die UX zu verbessern und zu vereinfachen. Das Standardformular mit Standard-Dateieingabe (+ multiple-Attribut) wird dort sein. Ich möchte die HTML5-Erweiterung hinzufügen.

edit
Ich weiß, in einigen -Browsern können Sie manchmal (fast immer) Dateien in die Dateieingabe selbst ablegen. Ich weiß, dass Chrome dies normalerweise tut, aber manchmal schlägt es fehl und lädt dann die Datei auf der aktuellen Seite (ein großer Fehler, wenn Sie ein Formular ausfüllen). Ich möchte es täuschen & browserfest machen.

127
Rudie

Ich habe eine Lösung dafür gemacht.

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

Die Drag & Drop-Funktion für diese Methode funktioniert nur mit Chrome, Firefox und Safari. (Weiß nicht, ob sie mit IE10 funktioniert), für andere Browser funktioniert die Schaltfläche "Oder klicken Sie hier".

Das Eingabefeld folgt einfach Ihrer Maus, wenn Sie eine Datei über einen Bereich ziehen, und ich habe auch eine Schaltfläche hinzugefügt.

Unkommentiert Opazität: 0; Die Dateieingabe ist nur sichtbar, damit Sie sehen können, was los ist.

44
BjarkeCK

Folgendes funktioniert in Chrome und FF, aber ich habe noch keine Lösung gefunden, die auch IE10 + abdeckt:

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

Sie möchten wahrscheinlich addEventListener oder jQuery (usw.) verwenden, um Ihre evt-Handler zu registrieren - dies ist nur der Kürze halber.

37
jlb

Dies ist der HTML5-Weg "DTHML". Normalform-Eingabe (die IS nur lesen kann, wenn Ricardo Tomasi darauf hinweist). Wenn eine Datei dann hineingezogen wird, wird sie an das Formular angehängt. Dies erfordert eine Änderung der Aktionsseite, um die auf diese Weise hochgeladene Datei zu akzeptieren.

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>

Es ist sogar noch vorbildlicher, wenn Sie das gesamte Fenster zu einer Drop-Zone machen können, siehe Wie erkenne ich, dass ein HTML5-Ziehereignis beim Betreten und Verlassen des Fensters erkannt wird, wie dies bei Gmail der Fall ist?

26

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

8
Dipak

Theoretisch könnten Sie ein Element hinzufügen, das das <input/> überlagert, und dann das Ereignis drop verwenden, um die Dateien (mithilfe der Datei-API) zu erfassen und an das Eingabe files-Array zu übergeben.

Außer dass eine Dateieingabe read-only ist. Das ist ein altes Problem.

Sie können jedoch die Formularsteuerung vollständig umgehen und über XHR hochladen (nicht sicher, welche Unterstützung dafür vorliegt):

Sie können auch ein Element in der Umgebung verwenden, um das Drop-Ereignis in Chrome abzubrechen und das Standardverhalten beim Laden der Datei zu verhindern.

Das Ablegen mehrerer Dateien über die Eingabe funktioniert bereits in Safari und Firefox.

6
Ricardo Tomasi

Ich weiß, dass einige Tricks in Chrome funktionieren. 

Wenn Sie Dateien in die Drop-Zone ziehen, haben Sie ein dataTransfer.files-Objekt, das heißt ein Objekttyp "FileList", das alle Dateien enthält, die Sie gezogen haben. Inzwischen besitzt das Element die Eigenschaft "files", d. H. Das gleiche Objekt vom Typ "FileList".

Daher können Sie das dataTransfer.files-Objekt einfach der input.files -Eigenschaft zuordnen.

3
Timur Gilauri

Für eine reine CSS-Lösung:

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

Geändert von https://codepen.io/Scribblerockerz/pen/qdWzJw

3
Jonathan

Tolle Arbeit von @BjarkeCK. Ich habe einige Änderungen an seiner Arbeit vorgenommen, um sie als Methode in jquery zu verwenden:

$.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();

Arbeiten Fiddle

1
Mr_Green

Einige Jahre später habe ich diese Bibliothek gebaut, um Dateien in beliebige HTML-Elemente zu kopieren.

Sie können es gerne verwenden

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();
1
Joel Hernandez

Für alle, die dies 2018 tun wollen, habe ich eine viel bessere und einfachere Lösung als alle alten Sachen, die hier veröffentlicht wurden. Sie können eine einfach aussehende Drag & Drop-Box nur mit Vanilla HTML, JavaScript und CSS erstellen.

(Funktioniert bisher nur in Chrome)

Beginnen wir mit dem HTML.

<div>
<input type="file" name="file" id="file" class="file">
<span id="value"></span>
</div>

Dann kommen wir zum Styling.

    .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%);
    }

Nachdem Sie dies getan haben, sieht es schon gut aus. Ich kann mir jedoch vorstellen, dass Sie gerne sehen möchten, welche Datei Sie wirklich hochgeladen haben. Wir werden also ein paar JavaScript-Anweisungen verwenden. Erinnern Sie sich an diesen PFP-Wert? Dort drucken wir den Dateinamen aus.

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;
    }
});

Und das ist es.

1
Michael

Damit bin ich herausgekommen. 

Jquery und Html verwenden. Dadurch wird es den Insert-Dateien hinzugefügt. 

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>

0
Lionel Yeo