68 votes

Téléchargement de fichiers par glisser-déposer dans Google Chrome/Chromium et Safari ?

Le téléchargement de fichiers par glisser-déposer est possible dans Firefox 3.6.

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

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

Cependant, Google a récemment publié une mise à jour pour Gmail qui permet le téléchargement de fichiers par glisser-déposer dans Chromium ainsi que dans Firefox, et Le chrome n'a pas FileReader . J'utilise la dernière version de Chromium nightly, et il est possible de télécharger des fichiers par glisser-déposer, mais il ne supporte pas FileReader .

J'ai vu quelqu'un mentionner que le téléchargement par glisser-déposer peut être possible en glissant sur une <input type="file" /> Mais il ne peut prendre en charge qu'un seul fichier à la fois, alors que l'outil de téléchargement de Gmail peut gérer plusieurs fichiers qui y sont glissés, donc ce n'est clairement pas ce qu'ils font.

La question est donc de savoir comment ils s'y prennent. Comment prendre en charge Chromium pour le téléchargement de fichiers HTML5 ? En outre, pouvez-vous prendre en charge Safari ?

33voto

Zarel Points 1711

AVERTISSEMENT : Il s'agit d'un code de compatibilité pour les très anciennes versions de Safari et de 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 n'est désormais utile que si, pour une raison ou une autre, vous avez besoin de prendre en charge Safari 5 et plus, ou Chrome 6 et plus.


Une possibilité est d'utiliser la méthode utilisée dans SwellJS :

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

<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) au-dessus d'un élément qui accepte les téléchargements. Le formulaire entier peut être placé à l'intérieur d'un iframe pour un comportement de type "pseudo-Ajax". Et l'élément de téléchargement peut être une couche caché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>

Cette opération ne doit être effectuée que lorsque Safari ou Chrome est détecté (les autres navigateurs ne prennent pas en charge le glisser-déposer sur le site de l'entreprise). <input type="file" /> ), et peuvent être utilisés en combinaison avec les éléments HTML5 drop pour Firefox 3.6+.

Je ne peux pas dire si c'est la méthode utilisée par Gmail, mais elle fonctionne certainement aussi bien.

13voto

Arnaud Leymet Points 2387

Vous pourriez être intéressé par quelque chose de plus conforme à la technologie et au navigateur.

Il me semble que Plupload le fait bien, en prenant en charge les fonctionnalités suivantes :

  • Chunking
  • Glisser/Déposer
  • Redimensionnement PNG
  • Redimensionnement de JPEG
  • Filtrage des types
  • Téléchargement de flux
  • Téléchargement multipartite
  • Restriction de la taille des fichiers
  • Télécharger les progrès

pour la plupart des technologies suivantes :

  • Flash
  • Engrenages
  • HTML 5
  • Silverlight
  • BrowserPlus

Et oui, depuis 2010.05.27 il prend en charge le glisser/déposer pour HTML5 fonctionnant sur Chrome beta.

10voto

Casey Chu Points 8804

J'ai réussi à faire fonctionner quelque chose dans Chrome après beaucoup, beaucoup, beaucoup de travail de détective. Voici seulement fonctionne sur Chrome. Sur Safari, il se fige. Sur Firefox, il ne me laisse 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 raison possible pour cela 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'));

2voto

Ryan Seddon Points 96

Vous n'auriez pas besoin d'utiliser une iframe pour faire du téléchargement pseudo ajax. Chrome et Safari prennent tous deux en charge Téléchargements XHR2 avec des événements de progression, ce qui permet de créer des barres de progression, etc.

2voto

Martin Points 21

Pour notre propre application, nous faisons du glisser-déposer pour FireFox uniquement. Nous revenons au téléchargement traditionnel par iframe pour les autres. Afin de détecter que le glisser-déposer est supporté, nous exécutons ce code :

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

J'espère que cela sera utile à certains.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X