Trochę czasu minęło od ostatniego wpisu, ale spowodowane był to tym, że wakacje i urlopy. Ale przejdźmy do rzeczy, tak jak obiecałem, w tym wpisie przedstawię, jak podzielić plik na części, aby ominąć limit danych (np. ten w PHP).
Dzielenie pliku na części nie jest tak skomplikowane jak
upload katalogów. Mamy jedną funkcje a właściwie metodę o nazwie
slice
, która wycina pewną część pliku. Metoda slice
ma swoje prefiksy w różnych przeglądarkach. Należy ona
do interface’u Blob, po którym dziedziczy obiekt File
(więcej o funkcji slice
na MDN). Wywołanie
metody zwraca nam obiekt typu Blob, który można z kolei dodać do obiektu
FormData, aby wysłać na serwer.
Kod, do dzielenia pliku na części oraz wgrywania ich na serwer, wygląda tak:
Najpierw definiujemy funkcję pomocniczą, która obsłuży prefiksy przeglądarek (1). W głównym kodzie zwracamy
obietnicę, w której mamy funkcję - wywołujemy ją pierwszy raz (9) z wartościami początkowymi. Już wewnątrz
funkcji, wycinamy cześć, którą wyślemy na serwer (2). Tworzymy obiekt FormData
(3) - w taki sposób wysyła
się pliki na serwer za pomocą AJAX-a. Następnie dodajemy naszą cześć (4). I wysyłamy na serwer za pomocą
funkcji fetch, która zwraca obietnicę. Jeśli się
powiedzie (nie będzię błędu HTTP) sprawdzamy, czy nie występuje jakiś inny błąd, który został wysłany z serwera
(zakładamy że serwer zwraca obiekt JSON). Jeśli wartość pola error
nie będzie wartością typu false
(może
być np. null
lub undefined
) to zwrócony zostanie wyjątek (6), który zostanie obsłużony przez metodę catch
obietnicy i zostanie odrzucona główna obietnica (8). W przypadku, gdy wszystko jest ok, zostanie wywołana
rekurencyjnie funkcja process
z nowymi wartościami wskazującymi na nowy kawałek pliku (7).
Aby taki kod zadziałał serwer musi być dodatkowo przygotowany. Skrypt upload.php
musi dodawać każdą następną
cześć na koniec pliku. Musi też być obsłużone nadpisywanie plików, np. gdy wgrywasz plik, który już istnieje
na serwerze. Wtedy musisz usunąć poprzedni plik, aby nie było w nim dwóch plików jeden za drugim.
W PHP można to osiągnąć, pisząc kod, który usunie plik przed zapisywaniem kolejnych części. (można np. dodać dodatkowy parametr dla pierwszej części pliku). Najpierw jednak dodajmy parametry w JavaScript.
Dodaliśmy kilka dodatkowych linijek kodu. W (1) tworzymy obiekt ustawień funkcji, który zawiera domyślną
wartość chunk: true
. W (2) dodajemy wszystkie opcje, te przekazane jako argument oraz domyślny chunk:
true
, do obiektu FormData
. W (3) przekazujemy dodatkową opcje first: true
, która zostanie przesłana do
serwera dzięki obiektowi FormData
(2). Będzie ona określała pierwszą część pliku.
Z takim kodem w JavaScript wystarczy że napiszemy nasz plik upload.php
:
Natomiast w kodzie PHP, po sprawdzeniu początkowych wyjątków, sprawdzamy czy mamy zdefiniowany zmienną POST o
nazwie first
. Jeśli tak to znaczy że musimy usunąć stary plik, ale tylko jeśli już istnieje (1). Następnie
pobieramy zawartość pliku (2), jeśli jest to część pliku (chunk), to otwieramy plik docelowy (3) i zapisujemy
zawartość tego co było przesłane (4), jeśli ilość bajtów się nie zgadza zwracany jest wyjątek. Jeśli nie jest
to część pliku tylko cały plik, używamy funkcji move_uploaded_file
. Jeśli zapis się powiedzie zwracamy JSON-a
z powodzeniem zapisu.
Dzięki takiemu plikowi mamy możliwość zwykłego uploadu oraz uploadu na części.
I to by było na tyle. Do tego kodu można by jeszcze dodać pasek postępu. Wystarczy obliczyć ile części zostanie wygenerowanych i procentowo zwiększać po wgraniu każdej z nich. Ale to zostawię jako ćwiczenie dla czytelnika.
Dodatkowo w kodzie PHP można jeszcze, tworzyć plik tymczasowy z częściami i tylko gdy całość zostanie poprawnie zapisana, nadpisywać oryginalny plik. Dzięki temu nie zostaniemy z niepełnym plikiem w docelowym miejscu. Plik tymczasowy natomiast, można usunąć przy pierwszym niepoprawnym zapisie.
Komentarze
Hasło, które podasz umożliwi ponowne zalogowanie się i np. usunięcie komentarza, jest dobrowolne. Email jest szyfrowany i używany do wysyłania powiadomień o odpowiedziach do komentarzy oraz do pobierania awatara dzięki usłudze Gravatar.com.