Hochladen von Dateien per Drag & Drop in Google Chrome / Chromium und Safari?

68

Das Hochladen von Dateien per Drag & Drop kann in Firefox 3.6 erfolgen.

Eine Google-Suche nach HTML5-Drag-and-Drop-Dateien zum Hochladen von -gmail bietet Dinge wie:

Alle diese Handbücher verwenden FileReader(oder die veralteten Firefox 3.6 getAsBinary, die auch kein anderer Browser unterstützt).

Google hat jedoch kürzlich ein Update für Google Mail veröffentlicht, das das Hochladen von Dateien per Drag & Drop in Chromium sowie in Firefox ermöglicht und in Chromium nicht verfügbar istFileReader . Ich verwende jeden Abend das neueste Chromium und es kann Upload-Dateien per Drag & Drop verschieben, ohne dies zu unterstützen FileReader.

Ich habe jemanden erwähnen sehen, dass das Hochladen per Drag & Drop durch Ziehen auf eine <input type="file" />Datei möglich ist , dies jedoch jeweils nur eine Datei unterstützt, während der Uploader von Google Mail mehrere Dateien verarbeiten kann, die darauf gezogen werden. Das ist also eindeutig nicht das, was sie sind tun.

Die Frage ist also, wie machen sie das? Wie unterstützen Sie das Hochladen von Chromium für HTML5-Dateien? Können Sie außerdem Safari unterstützen?

Zarel
quelle
2
PS Das Lesen des Quellcodes ist ziemlich schwierig, da der Quellcode von Google Mail aufgrund all der Optimierungen, die sie daran vornehmen, ziemlich gut verschleiert ist.
Zarel
1
PPS Das FileListeines HTML <input type="file" />- Codes ist schreibgeschützt, sodass Sie auch nicht einfach eine Drag-Drop-Datei in eine dieser Dateien übertragen können.
Zarel
Ist es möglich, den Titel dieses Beitrags zu ändern? Ich habe gerade doppelte Fragen zu "Drag & Drop" in "Chrome" gestellt, aber diese Frage stimmte nicht mit dieser überein, da der Titel Chromium verwendet (was die meisten Leute nicht verwenden).
Chris R
Okay, ich habe den Titel geändert.
Zarel

Antworten:

33

WARNUNG: Dies ist der Kompatibilitätscode für sehr alte Versionen von Safari und Chrome. Moderne Browser unterstützen alle die FileReader-API. Hier ist ein Tutorial: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Dieser Code ist jetzt nur dann nützlich, wenn Sie aus irgendeinem Grund Safari 5 und älter oder Chrome 6 und älter unterstützen müssen.


Eine Möglichkeit besteht darin, die in SwellJS verwendete Methode zu verwenden :

Verwenden Sie <input type="file" multiple="multiple" />wie folgt:

<form method="post" enctype="multipart/form-data" id="uploadform">
  <input type="file" name="dragupload[]" multiple="multiple"
  onchange="if (this.value) document.getElementById('uploadform').submit();" />
</form>

Das Eingabeelement kann so gestaltet werden, dass es opacity: 0(absolut) über einem Element liegt, das Uploads akzeptiert. Das gesamte Formular kann in ein iframefür "Pseudo-Ajax" ähnliches Verhalten eingefügt werden. Und das Upload-Element kann eine Ebene sein, die ausgeblendet wird, bis etwas darüber gezogen wird.

Ein solcher Iframe würde aussehen wie:

<script>
<!--
  var entered = 0;
-->
</script>
<body ondragenter="entered++;document.getElementById('uploadelement').style.display='block'" ondragleave="entered--;if (!entered) document.getElementById('uploadelement').style.display='none'">
  <form method="post" enctype="multipart/form-data" id="uploadform">
    Things can be dragged and dropped here!
    <input type="file" id="uploadelement" name="dragupload[]" multiple="multiple" onchange="if (this.value) { document.getElementById('uploadform').submit(); }" style="display:none;position:absolute;top:0;left:0;right:0;bottom:0;opacity:0;" />
  </form>
</body>

Dies sollte nur erfolgen, wenn Safari oder Chrome erkannt werden (da andere Browser das Ziehen und Ablegen auf <input type="file" />Elemente nicht unterstützen ) und kann in Kombination mit dem HTML5- dropEreignis für Firefox 3.6+ verwendet werden.

Ich kann nicht sagen, ob dies die Methode ist, die Google Mail verwendet, aber es funktioniert auf jeden Fall auch.

Zarel
quelle
Der Trick zum Erhöhen / Verringern der Eintragsanzahl in Ihrem Ein- / Ausblendcode ist sehr praktisch.
Sam Barnum
Vielen Dank für diesen Beitrag. Können Sie von hier aus auf ein vollständiges Beispiel verlinken? eine, die den serverseitigen Code enthalten kann? oder erklären Sie einfach (auf asp.net), wie ich auf die Dateien zugreifen kann, die von diesem Formular ("uploadForm") gesendet wurden
Guy
13

Möglicherweise interessieren Sie sich für etwas, das technologie- und browserkompatibler ist.

Mir scheint, dass Plupload es gut macht und die folgenden Funktionen unterstützt:

  • Chunking
  • Ziehen und loslassen
  • PNG Größe ändern
  • JPEG-Größenänderung
  • Typfilterung
  • Stream-Upload
  • Mehrteiliger Upload
  • Einschränkung der Dateigröße
  • Fortschritt hochladen

für die meisten der folgenden Technologien:

  • Blitz
  • Getriebe
  • HTML 5
  • Silverlight
  • BrowserPlus

Und ja, seit dem 27.05.2010 unterstützt es Drag & Drop für HTML5, das unter Chrome Beta ausgeführt wird.

Arnaud Leymet
quelle
Oh? Haben Sie die "HTML 5-Laufzeit" dieser Seite ausprobiert? plupload.com/example_all_runtimes.php
Arnaud Leymet
2
Die HTML5-Laufzeitversion funktioniert für mich mit 6.0.472.25 dev unter OS X. Sie scheint auch mit den Firefox 4-Betas zu funktionieren.
James Snyder
1
HTML5-Upload funktioniert für mich auch in Chrome 8.552.210 Beta unter WinXp (nur wenige Monate und sie haben 2 Versionen). Trotzdem danke für den Beitrag!
IgalSt
Für mich: Unter HTML5-Laufzeit funktioniert FF 15.0.1; Chrome 21 nicht.
Tim
10

Nach viel, viel, viel Detektivarbeit funktioniert in Chrome etwas. Dies funktioniert nur unter Chrome. Auf Safari friert es ein. Unter Firefox kann ich die Datei nicht löschen. IE öffnet stattdessen die abgelegte Datei. Selbst in Chrome funktioniert das Ziehen und Ablegen aus irgendeinem Grund nur einmal. Danach müssen Sie die Seite aktualisieren. (Ein möglicher Grund dafür ist, dass etwas mit den Ereignishandlern nicht stimmt.)

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <script type="text/javascript">
            window.onload = function () {
                var div = document.getElementById('div');
                div.ondragenter = div.ondragover = function (e) {
                    e.preventDefault();
                    e.dataTransfer.dropEffect = 'copy';
                    return false;
                }
                div.ondrop = function (e) {
                    for (var i = 0; i < e.dataTransfer.files.length; i++) { // e.dataTransfer is a DataTransfer object (https://developer.mozilla.org/En/DragDrop/DataTransfer), e.dataTransfer.files is a FileList object (https://developer.mozilla.org/en/DOM/FileList)
                        var file = e.dataTransfer.files[i]; // file is a File object (https://developer.mozilla.org/en/DOM/File)

                        var xhr = new XMLHttpRequest;
                        xhr.open('post', 'handler.php', true);
                        xhr.onreadystatechange = function () {
                            if (this.readyState != 4)
                                return;
                            document.body.innerHTML += '<pre>' + this.responseText + '</pre>';
                        }
                        xhr.setRequestHeader('Content-Type', 'multipart/form-data');
                        xhr.setRequestHeader('X-File-Name', file.fileName);
                        xhr.setRequestHeader('X-File-Size', file.fileSize);
                        xhr.send(file); // For some reason sending the actual File object in Chrome works?
                    }

                    e.preventDefault();
                    return false;
                }
            }
        </script>
    </head>
    <body>
        <div id="div" style="width: 100%; height: 200px; border: 1px solid blue">Drop here</div>
    </body>
</html>

handler.php:

    // This is not a true file upload. Instead, it sends the raw data directly.
    echo htmlentities(file_get_contents('php://input'));
Casey Chu
quelle
3
Die Verwendung von document.body.innerHTML + = zerstört die dom-Ereignisse. Wenn Sie dies vermeiden, wird Ihr Problem behoben.
Joseph Montanez
funktioniert super, mir wurde von einem Google Mail-Entwickler gesagt, dass Sie dropEffect = 'move' für FF3.6 + verwenden sollten, noch nicht in FF getestet, also nicht sicher, ob dies noch erforderlich ist
gatapia
2

Sie müssten keinen Iframe verwenden, um Pseudo-Ajax-Uploads durchzuführen. Chrome und Safari unterstützen beide XHR2-Uploads mit Fortschrittsereignissen, sodass Sie Fortschrittsbalken usw. erstellen können.

Ryan Seddon
quelle
... ja, so viel ist offensichtlich. Das Problem hierbei ist, dass alle Tutorials, die ich gesehen habe, eine Datei verwenden FileReaderoder getAsBinary()(dh die Funktionen, die Chrome nicht unterstützt) zum XHR2-Hochladen einer Datei verwenden. Ich bezweifle, dass dies erforderlich ist. Ich frage hier also im Grunde, wie man vorgehen soll, wenn man Chrome-Unterstützung wünscht.
Zarel
2

Für unsere eigene Anwendung ziehen und ziehen wir nur für FireFox. Wir kehren zum traditionellen Iframe-Upload für andere zurück. Um festzustellen, dass Drag & Drop unterstützt wird, führen wir diesen Code aus:

if (typeof(window.File) == 'object' && typeof(window.FileReader) == 'function' && typeof(window.FileList) == 'object') {
   // DnD is supported!
}

Hoffe das ist hilfreich für einige.

Martin
quelle
Sie erwähnen, dass Sie nur für FireFox ziehen und ablegen, aber für andere, die diesen Code verwenden, gibt Safari 5 (Windows) für die window.FileReaderPrüfung false zurück , obwohl es das Löschen von Dateien einwandfrei handhabt. Immer noch auf der Suche nach einer zuverlässigen Browser-Fähigkeitserkennung für Drag & Drop von Dateien ...
Chris
1

Die neueste Browser-Support-Datei kann gut hochgeladen werden. Du könntest benutzen:

xhr = new XMLHttpRequest();     
xhr.open('POST', targetPHP, true);
var formData = new FormData();
formData.append('upload',file);
xhr.send(formData);

Sie müssen weder eine Grenze noch einen Kopf festlegen. Einfach so funktioniert es einwandfrei. Ich habe diesen Code in Client: Firefox 6.02 und in Chrome 13 getestet. Server: Tomcat mit "Spring MVC"

Sommer-
quelle
0

Sie können FormData verwenden, um die Datei zu speichern und dann hochzuladen. z.B

function setUp(){
  var dropContainer = document.getElementById("container");
  dropContainer.addEventListener("drop",dropHandler,false);
  dropContainer.addEventListener("dragenter", function(event){event.stopPropagation();event.preventDefault();}, false);
  dropContainer.addEventListener("dragover", function(event){event.stopPropagation();event.preventDefault();}, false);
  dropContainer.addEventListener("drop", dropHandler, false);
  getResult()
}
function dropHandler(event){
  var files = event.dataTransfer.files;
  var count = files.length;
  form = new FormData();
  for(var i= 0;i<count;i++){
    form.append("file"+i, files[i]);
  }
  sendData();
}
function sendData(){
  var xhr = new XMLHttpRequest();  
  xhr.upload.addEventListener("progress", uploadProgress, false);  
  xhr.addEventListener("load", uploadComplete, false);
  xhr.addEventListener("error", uploadFailed, false);  
  xhr.open("POST", "/upload");
  xhr.send(form);
  var progressBar = document.getElementById('progressBar');
  progressBar.style.display = 'block';
  progressBar.style.width = '0px';
}

Die Demo ist hier (http://flexinnerp.appspot.com/), genieße es einfach :)

tai
quelle
0

Stellen Sie mehrere Attribute wie folgt ein:

Eingabetyp = "Datei" Name = "Datei1" multiple = "multiple" class = "DropHere"

und verwenden Sie diese CSS DropHere-Klasse:

.DropHere
{
    height: 100px;
    padding: 3px;
    border: 2px dashed #555;
    border-radius: 5px;
    cursor: default;
    background-image:url("data:image/svg+xml;utf8, <svg xmlns='http://www.w3.org/2000/svg' version='1.1' height='100px' width='220px'><text x='55' y='75' font-size='20'>or drop files here</text></svg>");
    background-repeat: no-repeat;
}

Das Dateifeld sieht nun folgendermaßen aus:

Die Datei sieht nun so aus

Wenn Sie asp.net verwenden, könnte Ihnen auch dieser Artikel gefallen. Ich habe "Hochladen mehrerer Dateien mit Fortschrittsbalken und Ziehen und Ablegen" geschrieben: http://www.codeproject.com/Articles/818561/Multiple-file-upload-with-progress -bar-and-drag-an

Igor Krupitsky
quelle