em
js-logo

Drag and drop file upload com JavaScript

Quando estamos editando o nosso portfólio em algum sistema web, temos um área para podermos arrastar uma nova foto que queremos, por exemplo, deixar de avatar. A implementação desse clica e arrasta (Drag and Drop) pode ser feita com JavaScript.

Neste post vamos desenvolver o Drag and Drop File Upload com JavaScript puro (VanillaJS) utilizando a File API. E no Backend também vamos utilizar JavaScript com o NodeJS + Express + Handlebars.

Caso você ainda não tenha o NodeJS instalado, no próprio site do NodeJS existe um intalador super intuitivo, onde basta dar next, next e next. Segue link para download do instalador do NodeJS.

Pronto! Agora que temos o NodeJS instalado podemos seguir com o tutorial do Drag and Drop File Uplaod em VanillaJS.

Não vou entrar em grandes detalhes sobre o NodeJS, ExpressJS ou Handlebars. Nosso foco será no JavaScript.

Segue abaixo o HTML, CSS e JavaScript que vamos utilizar:

HTML

O HTML não tem muito segredo. Utilizamos algumas tags do HTML5 (header, article e footer) e um pouco da implementação do formulário com HTML5. O que vale a pena destacar é o atributo multiple do input com o tipo file, que está na linha 33. Este atributo permite a seleção de múltiplos arquivos.

<article id="home-article">
    <form id="home-article-signup" action="">
        <legend class="form-title space-bottom-medium">Login Credentials</legend>

        <fieldset class="fleft space-bottom-small">
            <label for="article-signup-first-name" class="form-label">First Name</label>
            <input id="article-signup-first-name" class="form-text space-bottom-small" name="first-name" type="text" placeholder="e.g., Marco" tabindex="1" autofocus required="required">

            <label for="article-signup-email" class="form-label">Email</label>
            <input id="article-signup-email" class="form-text space-bottom-small" name="email" type="email" placeholder="marco.bruno.br@gmail.com" tabindex="3" required="required">

            <label for="article-signup-password" class="form-label">Password</label>
            <input id="article-signup-password" class="form-text space-bottom-small" name="password" type="password" placeholder="********" tabindex="5" required="required">
        </fieldset><!-- .fleft -->

        <fieldset class="fright space-bottom-small">
            <label for="article-signup-last-name" class="form-label">Last Name</label>
            <input id="article-signup-last-name" class="form-text space-bottom-small" name="last-name" type="text" placeholder="Bruno" tabindex="2" required="required">

            <label for="article-signup-re-enter-email" class="form-label">Re-enter Email</label>
            <input id="article-signup-re-enter-email" class="form-text space-bottom-small" name="re-enter-email" type="email" placeholder="marco.bruno.br@gmail.com" tabindex="4" required="required">

            <label for="article-signup-re-enter-password" class="form-label">Re-enter Password</label>
            <input id="article-signup-re-enter-password" class="form-text space-bottom-small" name="re-enter-password" type="password" placeholder="********" tabindex="6" required="required">
        </fieldset><!-- .fright -->

        <fieldset class="clear">
            <label for="article-signup-upload" class="form-label">Files Upload</label>            
            
            <input id="uploadfile" class="form-text fleft space-right-small space-bottom-small" type="text" disabled="disabled">
            <filendset class="wrap-form-upload btn btn-primary fright">
                <span>Upload</span>
                <input id="article-singup-upload" class="form-upload" type="file" name="upload[]" multiple="multiple" required="required">
            </filendset><!-- .wrap-form-upload-->

            <fieldset id="form-drag-and-drop">
                <label class="drag-and-drop-label">or Drag and drop files/folders from your desktop</label>                                        
            </fieldset><!-- #form-drag-and-drop -->

            <label class="form-label">Files/Folder to Upload</label>
            <label id="output" class="space-bottom-medium"></label>

            <input id="article-signup-action" class="btn btn-primary clear" type="submit" value="Submit" tabindex="7">
        </fieldset>
    </form><!-- #home-article-signup -->
</article><!-- #home-article -->

CSS

Como no HTML o CSS não tem nada demais, mas podemos dizer que temos algumas implementações do CSS3 como o transition, border-radius e opacity. Mas o ponto que deve ganhar um destaque de verdade é o parte que da estilo ao input do tipo file que está entre as linhas 42 e 67:

.form-title {
    font-size: 25px;
    color: #000;
}
.form-text {
    border: 1px solid #CCC;
    box-shadow: 0px 1px 3px #DDD inset;
    border-radius: 4px;
    padding: 5px 8px;
    height: 22px;
    line-height: 22px;

    -webkit-transition: all 0.5s linear;
        -moz-transiton: all 0.5s linear;
            transition: all 0.5s linear;
}
.form-text:focus {
    border-color: #6D8CCE;
    box-shadow: 0px 1px 3px #EEE inset;
    outline: none;
}
.btn {
    display: block;
    font-size: 16px;
    cursor: pointer;
    height: 40px;
    line-height: 40px;
    text-align: center;
    padding-left: 20px;
    padding-right: 20px;
    border-radius: 2px;

    -webkit-transition: all 0.2s linear;
       -moz-transition: all 0.2s linear;
            transition: all 0.2s linear:
}
.btn-primary {
    background-color: #6D8CCE;
    color: #FFF;
}
.form-action:hover { background-color: #5073BA; }
.wrap-form-upload {
    position: relative;
    overflow: hidden;
    height: 34px;
    line-height: 34px;
}
.form-upload {
    position: absolute;
    top: 0;
    right: 0;
    cursor: pointer;
    opacity: 0;
    filter: alpha(opacity=0);
}

#form-drag-and-drop {
    border: 4px dotted #BFBFBF;
    border-radius: 5px;
    height: 100px;
    width: 492px;
}
.drag-and-drop-label {
    text-align: center;
    line-height: 100px;
    display: inherit;
}

JavaScript

O JavaScript é dividido em 4 arquivos:

Vamos explicar a responsabilidade de cada arquivo abaixo.

util.js

Não vou entrar em detalhes de como funciona o escopo em JavaScript, nem falar sobre OO (Orientação a Objetos) para JavaScript, por ser um assunto bem extenso, mas se você se interessa sobre o assunto, eu recomendo a vídeo aula do William Bruno, JavaScript – Boas práticas e otimização.

Este JavaScript tem apenas um loop um pouco otimizado para percorrer uma lista, sem se preocupar com a ordem ou qual index está.

var util = (function () {
    'use strict';

    var module = {};

    module.loop = function (elements, callback) {
        var max = elements.length;

        while (max--) {
            callback(elements[max]);
        };
    };

    return {
        loop: module.loop
    };
})();

XHR.js

Esse JavaScript é responsável pelo Ajax. Apenas isso. :-)

var XHR = (function () {
    'use strict';

    var module = {};

    module.init = function () {
        return new XMLHttpRequest();
    };

    return {
        init: module.init
    }
})();

FileApi.js

Esse é o objeto responsável por fazer o drag and drop de seu arquivo.

var FileApi = (function (document) {
    'use strict';

    var module = {};

    module.dragHover = function (event) {
        event.stopPropagation();
        event.preventDefault();
    };

    module.selectMultiple = function (event, callback) {
        var files = event.target.files || event.dataTransfer.files;

        callback(files);
    };

    return {
        dragHover: module.dragHover,
        selectMultiple: module.selectMultiple
    };

})(document);

index.js

Esse é o cara que utiliza todos os outros aquivos JS e trata de dar um feedback pro usuário do que está acontecendo, manipulando o DOM.

(function (document) {
    'use strict';

    var $btnupload = document.getElementById('article-singup-upload'),
        $uploadfile = document.getElementById('uploadfile'); 

    var Output = function (msg) {
        var m = document.getElementById("output");

        m.innerHTML = msg + m.innerHTML;
    };

    var ParseFile = function (files) {
       util.loop(files, function (file) {
            Output(
                "

File information: " + file.name + "

" ); }); }; if (window.File && window.FileList && window.FileReader) { var fileselect = document.getElementById('article-singup-upload'), filedrag = document.getElementById('form-drag-and-drop'); fileselect.addEventListener('change', function (event) { console.log(this); FileApi.dragHover(event); FileApi.selectMultiple(event, ParseFile); }, false); var xhr = XHR.init(); if (xhr.upload) { filedrag.addEventListener("dragover", FileApi.dragHover, false); filedrag.addEventListener("dragleave", FileApi.dragHover, false); filedrag.addEventListener("drop", function (event) { FileApi.dragHover(event); FileApi.selectMultiple(event, ParseFile); }, false); }; }; })(document);

Se você quiser acesso a parte do backend eu deixe o código completo no Github:
https://github.com/MarcoBruno/drag-and-drop-file-upload

Você já precisou utilizar esse recurso de Drag and Drop File Upload? Como você fez? O que você melhoria nesse código?

Comentários

  1. Muito bom o artigo. Foi muito útil para mim ajá visto que fazemos questão de desenvolver sites com apenas HTML e JavaScritp.

    Obrigado.

    por Alexandre Alves Responder

Deixe uma resposta

O seu endereço de email não será publicado Campos obrigatórios são marcados *

Você pode usar estas tags e atributos de HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>