Upload plików bez przeładowania strony

uploadJednym z ciekawszych zastosowań AJAX-a i HTML5, które poszerza funkcjonalność zwykłej strony i usprawnia interakcje użytkownika jest upload plików bez przeładowania strony. File API wprowadzone w HTML5 daje koderowi opcje przekazywania informacji o plikach za pomocą XMLHttpRequest. Oczywiście, również do tego celu powstały dziesiątki rozszerzeń i gotowych skryptów, które wystarczy dodać na stronę, skonfigurować i nie martwić się o nic więcej.

Ja szukałem jednak czegoś jak najprostszego, aby samodzielnie dopasować do wcześniej stworzonej już aplikacji. Znalazłem ostatecznie plugin jQuery o nazwie LiteUploader – naprawdę prosta wtyczka o dużych możliwościach, wszystko sprowadza się do inicjalizacji i wykorzystania odpowiednich zdarzeń.

Oprócz kodu JavaScript potrzebny będzie plik PHP, który odbierze plik i zapisze na serwerze. Zasada działania nie różni się wiele od zwykłego uploadu – musimy:

  • za pomocą tablicy $_FILES zobaczyć czy załadowanie pliku się udało
  • sprawdzić format pliku i/lub jego wagę, jeśli chcemy
  • przenieść plik tymczasowy do docelowego folderu
  • zwrócić rezultat – przekazać wiadomość o powodzeniu lub błędzie

Zacznę jednak od kodu HTML na stronie, czyli przede wszystkim zwykłego pola o identyfikatorze fileUpload:

<input type="file" name="file" id="file_upload" />
<button type="button" id="upload_button">Upload</button>

Jak widać, mamy tam pole umożliwiające upload pliku oraz przycisk zatwierdzający. Tyle jak na razie w zupełności nam wystarczy.

Kolej na wspomniany plik PHP, można go nazwać np. ajax_file_uploader.php i wrzucić do głównego folderu strony.

<?php

if($_FILES['file']['name'][0]) {
    $path = 'files/'.$_FILES['file']['name'][0];
    if(move_uploaded_file($_FILES['file']['tmp_name'][0], $path)) {
        echo json_encode('ok');
        exit;
    }
}

echo json_encode('error');

?>

Wybrany plik zostanie skopiowany do folderu files (trzeba go jednak najpierw utworzyć i ustawić odpowiednie uprawnienia) pod oryginalną nazwą. W przypadku powodzenia żądanie zwróci do przeglądarki ciąg ok, w przeciwnym razie error. Na marginesie: jeśli informacje o pliku zapisujecie również w bazie danych, być może przydatne będzie zamiast komunikatu ok przekazanie identyfikatora w tabeli dodanego rekordu.

Teraz ściągamy LiteUploader (https://raw.githubusercontent.com/burt202/lite-uploader/master/jquery.liteuploader.min.js) oraz jQuery (http://code.jquery.com/jquery.min.js) i wgrywamy na serwer, a następnie dołączamy do strony:

<script type="text/javascript" src="js/jquery.min.js"></script>
<script type="text/javascript" src="js/jquery.liteuploader.min.js"></script>

a następnie zabieramy się do pisania kodu, który “ożywi” nasz dotychczasowy formularz przy pomocy LU. Można umieścić go razem z jquery.liteuploader.min.js np. jako uploader.js (oczywiście nie zapominając o załączeniu go w sekcji head!).

$(document).ready(function() {

    $('#file_upload').liteUploader({
        'script': 'ajax_file_uploader.php',
        'changeHandler': false,
        'clickElement': $('#upload_button')
    })
    .on('lu:before', function(e, files) {
        if($('#upload_status').length == 0) $('#upload_button').after('<p id="upload_status">Wczytywanie: <span id="upload_percents">0</span>%</p>');
        else $('#upload_status').html('Wczytywanie: <span id="upload_percents">0</span>%');
    })

    .on('lu:progress', function(e, percentage) {
        $('#upload_percents').html(percentage);
    })

    .on('lu:errors', function(e, errors) {
        $('#upload_status').html('Wystąpił błąd');
    })

    .on('lu:success', function(e, response) {
        response = JSON.parse(response);
        if(response == 'ok') $('#upload_status').html('Zakończono sukcesem');
        else $('#upload_status').html('Wystąpił błąd');
    });

});

Po wybraniu pliku i kliknięciu przycisku obok powinno się rozpocząć proces wczytywania na serwer. Poniżej pojawi się komunikat:

Wczytywanie: 0%

który będzie się zmieniał w trakcie operacji. Niestety, nie będzie to zauważalne przy małych plikach, przy których praktycznie automatycznie pojawi się komunikat Zakończono sukcesem lub Wystąpił błąd.

Po analizie kodu, jeśli macie większą wiedzę w zakresie jQuery i CSS to na pewno uda Wam się przygotować jakiś loader graficzny obrazujący postęp przy przesyłaniu.

Zachęcam do przejrzenia dokumentacji i przetestowania m.in. przesyłania dodatkowych zmiennych wraz z plikiem przez POST czy zaawansowanej obsłudze komunikatów błędów.

komentarze 23 do “Upload plików bez przeładowania strony”

Skomentuj

CommentLuv