web-dev-qa-db-fra.com

Glisser-déposer des fichiers dans Google Chrome/Chromium et Safari?

Le téléchargement de fichiers par glisser-déposer peut être effectué dans Firefox 3.6.

Une recherche Google pour html5 lors du téléchargement de fichiers par glisser-déposer -gmail donne des informations comme:

Tous ces guides utilisent FileReader (ou la getAsBinary obsolète de Firefox 3.6, qu'aucun autre navigateur ne prend en charge).

Cependant, Google a récemment publié une mise à jour pour Gmail qui autorisait le téléchargement de fichiers par glisser-déposer dans Chromium et Firefox, et Chromium n'a pas FileReader . J'utilise la dernière version de Chromium tous les soirs et il peut glisser-déposer des fichiers de téléchargement sans prendre en charge FileReader.

J'ai vu quelqu'un mentionner que l'envoi par glisser-déposer peut être possible en glissant sur un <input type="file" />, mais que celui-ci ne peut prendre en charge qu'un fichier à la fois, alors que le programme de téléchargement de Gmail peut gérer plusieurs fichiers qui y sont déplacés. re faire.

La question est donc de savoir comment ils le font. Comment supportez-vous Chromium pour le téléchargement de fichiers HTML5? De plus, pouvez-vous soutenir Safari?

68
Zarel

AVERTISSEMENT: Ceci est un code de compatibilité pour les très anciennes versions de Safari et Chrome. Les navigateurs modernes prennent tous en charge l’API FileReader; voici un tutoriel: https://developer.mozilla.org/en-US/docs/Using_files_from_web_applications

Ce code est désormais utile uniquement si, pour une raison quelconque, vous devez prendre en charge Safari version 5 ou antérieure, ou Chrome 6 et version ultérieure.


Une possibilité consiste à utiliser la méthode utilisée dans SwellJS :

Utilisez <input type="file" multiple="multiple" /> comme suit:

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

L'élément d'entrée peut être stylé pour avoir opacity: 0 et positionné (absolument) sur un élément qui accepte les téléchargements. Le formulaire entier peut être placé dans une variable iframe pour "pseudo-Ajax". Et l'élément de téléchargement peut être une couche masquée jusqu'à ce que quelque chose soit glissé dessus.

Un tel iframe ressemblerait à ceci:

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

Cela ne devrait être fait que lorsque Safari ou Chrome est détecté (car les autres navigateurs ne prennent pas en charge le glisser-déposer sur les éléments <input type="file" />) et peut être utilisé en combinaison avec l'événement HTML5 drop pour Firefox 3.6+.

Je ne peux pas dire s'il s'agit de la méthode utilisée par Gmail, mais cela fonctionne certainement aussi.

33
Zarel

Vous pourriez être intéressé par quelque chose de plus compatible avec la technologie et le navigateur.

Il me semble que Plupload le fait bien, supportant les fonctionnalités suivantes:

  • Chunking
  • Drag/Drop
  • PNG Redimensionner
  • JPEG Redimensionner
  • Filtrage de type
  • Envoi de flux
  • Envoi multipart
  • Limitation de la taille du fichier
  • Progression du téléchargement

pour la plupart des technologies suivantes:

  • Flash
  • Engrenages
  • HTML 5
  • Silverlight
  • BrowserPlus

Et oui, depuis le 2010.05.27 , il prend en charge le glisser-déposer pour HTML5 exécuté sur la version bêta de Chrome.

13
Arnaud Leymet

J'ai quelque chose qui fonctionne dans Chrome après beaucoup, beaucoup, beaucoup de travail de détective. Ceci seulement fonctionne sur Chrome. Sur Safari, il gèle. Sur Firefox, cela ne me laissera pas déposer le fichier. IE ouvre le fichier déposé à la place. Même dans Chrome, le glisser-déposer ne fonctionne qu'une fois, pour une raison quelconque, après quoi vous devez actualiser la page. (Une des raisons possibles est que quelque chose ne va pas avec les gestionnaires d'événements.)

<!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'));
10
Casey Chu

Pour notre propre application, nous ne faisons glisser que pour FireFox. Nous revenons au téléchargement traditionnel d'iframe pour les autres. Afin de détecter que le glisser-déposer est pris en charge, nous lançons ce code:

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

J'espère que cela est utile pour certains.

2
Martin

Vous n'avez pas besoin d'utiliser un iframe pour effectuer un téléchargement pseudo-ajax. Chrome et Safari prennent tous deux en charge les téléchargements XHR2 avec des événements de progression afin que vous puissiez créer des barres de progression, etc.

2
Ryan Seddon

Vous pouvez utiliser la bibliothèque html5uploader: http://code.google.com/p/html5uploader/

Cela fonctionne avec Firefox, Safari et Chrome.

2
WOj

Le dernier fichier supporté par le navigateur permet de charger correctement le fichier . Vous pouvez utiliser:

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

Vous n'avez pas besoin de définir de limite ni de tête , juste comme ça, cela fonctionne très bien . J'ai testé ce code dans Client: firefox 6.02 et en chrome 13 . Serveur: Tomcat avec "spring mvc"

1
summer

Définir plusieurs attributs comme:

type d'entrée = "fichier" name = "fichier1" multiple = "multiple" class = "DropHere"

et utilisez cette classe CSS DropHere:

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

Le champ de fichier ressemblera maintenant à:

The file will now look like

Si vous utilisez asp.net, vous aimerez peut-être aussi cet article que j’ai écrit "Téléchargement de plusieurs fichiers avec barre de progression et glisser-déposer": http://www.codeproject.com/Articles/818561/Multiple-file-upload-with -progress-bar-and-drag-an

0
Igor Krupitsky

vous pouvez utiliser FormData pour stocker le fichier, puis le télécharger. par exemple 

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

la démo est ici (http://flexinnerp.appspot.com/) Profitez-en :)

0
tai