Formulář pro nahrání souboru Mini AJAX

V tomto tutoriálu vytvoříme formulář pro nahrávání souborů AJAX, který umožní návštěvníkům nahrávat soubory z jejich prohlížečů přetažením/upuštěním nebo jejich individuálním výběrem. Za tímto účelem zkombinujeme výkonný plugin jQuery File Upload s elegantním jQuery Knob, abychom představili úhledné rozhraní založené na CSS3/JS.

HTML

Jako obvykle začneme základním dokumentem HTML5:

<!DOCTYPE html>
<html>

    <head>
        <meta charset="utf-8"/>
        <title>Mini Ajax File Upload Form</title>

        <!-- Google web fonts -->
        <link href="http://fonts.googleapis.com/css?family=PT+Sans+Narrow:400,700" rel='stylesheet' />

        <!-- The main CSS file -->
        <link href="assets/css/style.css" rel="stylesheet" />
    </head>

    <body>

        <form id="upload" method="post" action="upload.php" enctype="multipart/form-data">
            <div id="drop">
                Drop Here

                <a>Browse</a>
                <input type="file" name="upl" multiple />
            </div>

            <ul>
                <!-- The file uploads will be shown here -->
            </ul>

        </form>

        <!-- JavaScript Includes -->
        <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
        <script src="assets/js/jquery.knob.js"></script>

        <!-- jQuery File Upload Dependencies -->
        <script src="assets/js/jquery.ui.widget.js"></script>
        <script src="assets/js/jquery.iframe-transport.js"></script>
        <script src="assets/js/jquery.fileupload.js"></script>

        <!-- Our main JS file -->
        <script src="assets/js/script.js"></script>

    </body>
</html>

V záhlaví dokumentu jsem zahrnul dva fonty z Google Webfonts a před závěrečným tagem můžete vidět řadu knihoven JavaScriptu. Jedná se o knihovnu jQuery, plugin jQuery Knob a závislosti pro plugin jQuery File Upload.

Hlavním prvkem na stránce je #upload formulář. Uvnitř je #kapka div (který přijímá stahování přetažením) a neuspořádaný seznam. Tento seznam bude obsahovat li položku pro každý z přenesených souborů. Označení generované pro nahrání souboru můžete vidět níže:

<li class="working">
    <input type="text" value="0" data-width="48" data-height="48" data-fgColor="#0788a5" data-readOnly="1" data-bgColor="#3e4043" />
    <p>Sunset.jpg <i>145 KB</i></p>
    <span></span>
</li>

Vstupní položka ve výše uvedeném úryvku je skryta pomocí CSS. Jeho jediným účelem je inicializovat plugin jQuery Knob, který bude mít na výstupu pěkný ovládací knoflík knobu založený na plátně. Vstup má číslo data-* atributy, které upravují vzhled knoflíku. Později, když nasloucháme průběhu nahrávání souboru, aktualizujeme hodnotu tohoto vstupu, což způsobí překreslení knoflíku. Rozpětí drží ikonu vpravo; může to být zaškrtnutí nebo červený křížek.

Kód jQuery

Existují dva způsoby, jak může návštěvník nahrát soubory pomocí tohoto formuláře:

  • Upuštěním na #drop div (ve všech prohlížečích kromě IE);
  • Kliknutím na tlačítko procházet. To bude simulovat kliknutí na skrytý vstup souboru, který vyvolá okno pro procházení souborů systému. Všimněte si, že vstup souboru má násobek sada parametrů, která umožní vybrat více než jeden soubor v daný čas (soubory však budou stále nahrány jednotlivě!).

Výchozí chování pluginu je umístit soubory do fronty, ale soubory nahrajeme automaticky, když jsou vypuštěny/vybrané, což zjednoduší práci. JS můžete vidět níže:

assets/js/script.js

$(function(){

    var ul = $('#upload ul');

    $('#drop a').click(function(){
        // Simulate a click on the file input button
        // to show the file browser dialog
        $(this).parent().find('input').click();
    });

    // Initialize the jQuery File Upload plugin
    $('#upload').fileupload({

        // This element will accept file drag/drop uploading
        dropZone: $('#drop'),

        // This function is called when a file is added to the queue;
        // either via the browse button, or via drag/drop:
        add: function (e, data) {

            var tpl = $('<li class="working"><input type="text" value="0" data-width="48" data-height="48"'+
                ' data-fgColor="#0788a5" data-readOnly="1" data-bgColor="#3e4043" /><p></p><span></span></li>');

            // Append the file name and file size
            tpl.find('p').text(data.files[0].name)
                         .append('<i>' + formatFileSize(data.files[0].size) + '</i>');

            // Add the HTML to the UL element
            data.context = tpl.appendTo(ul);

            // Initialize the knob plugin
            tpl.find('input').knob();

            // Listen for clicks on the cancel icon
            tpl.find('span').click(function(){

                if(tpl.hasClass('working')){
                    jqXHR.abort();
                }

                tpl.fadeOut(function(){
                    tpl.remove();
                });

            });

            // Automatically upload the file once it is added to the queue
            var jqXHR = data.submit();
        },

        progress: function(e, data){

            // Calculate the completion percentage of the upload
            var progress = parseInt(data.loaded / data.total * 100, 10);

            // Update the hidden input field and trigger a change
            // so that the jQuery knob plugin knows to update the dial
            data.context.find('input').val(progress).change();

            if(progress == 100){
                data.context.removeClass('working');
            }
        },

        fail:function(e, data){
            // Something has gone wrong!
            data.context.addClass('error');
        }

    });

    // Prevent the default action when a file is dropped on the window
    $(document).on('drop dragover', function (e) {
        e.preventDefault();
    });

    // Helper function that formats the file sizes
    function formatFileSize(bytes) {
        if (typeof bytes !== 'number') {
            return '';
        }

        if (bytes >= 1000000000) {
            return (bytes / 1000000000).toFixed(2) + ' GB';
        }

        if (bytes >= 1000000) {
            return (bytes / 1000000).toFixed(2) + ' MB';
        }

        return (bytes / 1000).toFixed(2) + ' KB';
    }

});

Knihovna jQuery File Upload přichází s vlastním designem založeným na jQuery UI, který můžete ihned používat. Protože však potřebujeme zcela vlastní rozhraní, použijeme základní verzi pluginu, která rozhraní neobsahuje. Aby to fungovalo, předáváme řadu konfiguračních možností / zpětných volání. Ve výše uvedeném kódu jsou tyto:

  • dropZone - Tato vlastnost obsahuje selektor jQuery prvku, který bude fungovat jako cíl přetažení. Soubory, které jsou na něj umístěny, budou přidány do fronty pro nahrávání.
  • přidat - Tato funkce zpětného volání je volána vždy, když je soubor přidán do fronty. Uvnitř vytvoříme značku HTML, která bude reprezentovat soubor, přidáme jej do UL a spustíme data.submit() metoda. To způsobí, že přidaný soubor bude přímo nahrán bez čekání.
  • pokrok - Toto zpětné volání provádí plugin každých 100 ms (lze konfigurovat). Druhý argument (atribut data) obsahuje velikost souboru a počet přenesených bajtů. To nám umožňuje vypočítat procento a následně aktualizovat skrytý vstupní prvek, který zase aktualizuje knoflík.
  • selhání - Tato funkce zpětného volání se spustí, pokud dojde k problému s vaším PHP skriptem. To by s největší pravděpodobností znamenalo, že soubor upload.php chybí nebo hází nějakou chybu (pro odladění případných problémů zde použijte inspektor vašeho webového prohlížeče).

data.context vlastnost je zachována mezi voláními metod pluginu. Tímto způsobem víme, kterou položku LI bychom měli aktualizovat v událostech progress a fail.

Skript PHP

jQuery File Upload také přichází s výkonným PHP skriptem pro zpracování nahrávání souborů, který můžete umístit na svůj server, ale pro tento tutoriál si vytvoříme vlastní. Nahrání souborů odesílaných pluginem je prakticky stejné jako běžné nahrání formuláře – k informacím o nahráních můžete přistupovat prostřednictvím pole $_FILES:

<?php

// A list of permitted file extensions
$allowed = array('png', 'jpg', 'gif','zip');

if(isset($_FILES['upl']) && $_FILES['upl']['error'] == 0){

    $extension = pathinfo($_FILES['upl']['name'], PATHINFO_EXTENSION);

    if(!in_array(strtolower($extension), $allowed)){
        echo '{"status":"error"}';
        exit;
    }

    if(move_uploaded_file($_FILES['upl']['tmp_name'], 'uploads/'.$_FILES['upl']['name'])){
        echo '{"status":"success"}';
        exit;
    }
}

echo '{"status":"error"}';
exit;

Jak jsem uvedl dále, ačkoli můžeme vybrat spoustu souborů najednou, jsou nahrány jeden po druhém. Díky tomu je ještě snazší s nimi pracovat pomocí našeho PHP skriptu. V současné době se soubory jednoduše přesouvají do složky pro nahrávání, ale můžete ji rozšířit přidáním ověřování nebo vytvořením záznamů ve vaší databázi.

Máme hotovo!

Doufám, že tento formulář pro nahrání souboru ajax pro vás bude užitečný! Pokud máte návrhy nebo dotazy, zanechte je v oblasti komentářů.

Zdroje a další čtení

  • Domovská stránka pluginu jQuery Knob
  • Stránka github pluginu jQuery File Upload
  • jQuery File Upload API
  • Možnosti nahrávání souboru jQuery
  • Nejčastější dotazy k nahrávání souboru jQuery
  • Jak vylepšit zónu přetažení pomocí efektů přetažení
  • Snímek Dribbble, kterým byl inspirován návrh tohoto výukového programu