Dzisiaj jest poniedziałek, 25 września 2017
JAK wkurzyć grafika (i nie tylko)JAKIE błędy popełniamy w Corelu?Dlaczego jesteś głupi, chory i biedny?
Jak rozwiązać problem z FormData w Safari?

Jak rozwiązać problem z FormData w Safari?

czwartek, 2017-06-22401tutoriale, internet, Alib CyMeS

Siedziałem sobie niedawno w Zamkowych Tarasach z waniliowym latte w kubku i Macbookiem przed sobą. Kawa nie była ze Starbucksa, bo go nie ma jeszcze w Lublinie, ale Mac był jak najbardziej Applowski. Miałem potrzebę wysłać tu na bloga kilka zdjęć. Skorzystałem więc ze swojego multiuploadera i... dupa. Nie działał. Jak to się mogło stać?

Jak wysyłać pliki Ajaxem?

Jeśli używasz przestarzałego #MSIE to na własne ryzyko
Zatweetuj

Od dawna rozwijam autorski Alib CyMeS. Jakiś rok temu zrezygnowałem z flashowego multiuploadera na rzecz JavaScriptowego wykorzystującego technologię HTML5AJAX. Wiadomo, Flash w internecie jest już przeżytkiem. Urządzenia mobilne go nie wspierają, Apple też się wypiął a i windowsowe przeglądarki robią coraz więcej problemów. Na szczęście HTML5 już dawno jest standardem i jeśli ktoś używa przestarzałego MSIE to na własne ryzyko.

Poczytałem trochę o wysyłaniu plików Ajaxem i wszędzie jednogłośnie zalecano używanie obiektu FormData.

W skrócie obiekt FormData umożliwia tworzenie par klucz-wartość reprezentujących pola formularzy, które potem łatwo przesłać w formacie „multipart/form-data” wykorzystując metodę send() obiektu XMLHttpRequest.

Jak to zrobić?

  1. W JavaScript tworzysz obiekt FormData
  2. Dodajesz do niego dane metodą append(), w której dla zwykłych danych przekazuje się dwa parametry (klucz i wartość) a dla plików trzy (dodatkowo nazwę pliku)
  3. Pchasz to wszystko Ajaxem na serwer, najlepiej przy pomocy jQuery, gdzie jednym z parametrów jest właśnie obiekt FormData
  4. Po stronie serwera odczytujesz wszystko normalnie z $_POST$_FILES

No i super. Oprogramowałem, sprawdziłem czy działa i zapomniałem o temacie.

Gdzieś popełniłem błąd?

@Safari wspiera tylko jedną metodę obiektu #FormData
Zatweetuj

No i właśnie niedawno próbuję tego użyć na Macbooku i dupa. Próbuje drugi raz i znowu bez skutku. Jako że akurat jestem w trakcie solidnej rozbudowy CMS-a, pomyślałem, że coś w międzyczasie zepsułem. Ale po powrocie do domu odpalam PC, Firefoxa i... ojejku, jakie zdziwienie! Wszystko działa poprawnie!

Uuu... - pomyślałem - jakaś grubsza sprawa.

Zacząłem szukać więcej informacji o obiekcie FormData i okazuje się, że Safari wspiera ten obiekt tylko na bardzo podstawowym poziomie, czyli metodę append(klucz,wartość). A ja używałem ich trochę więcej np. get()set().

A podobno produkty Apple (nie tylko sprzęt) są takie nowoczesne i podobno zgodne z najnowszymi trendami...

Żeby oddać sprawiedliwość, MSIE również nie obsługuje w pełni FormData, ale tu akurat problemu większego nie ma. W ta przeglądarka służy przede wszystkim do pobrania Firefoxa :)

Trzeba kombinować inaczej

Nie lubię korzystać z gotowców, bo ze względu na swoją uniwersalność są po prostu „przegadane”
Zatweetuj

Kolejne dwa dni kombinowałem, jak ten problem rozwiązać. Nie było łatwo, internet uparcie trzymał się FormData. Na szczęście wytrwałość w poszukiwaniach popłaciła. Znalazłem „zastępcze” prototypy a nawet jeden płatny plugin.

Niespecjalnie lubię korzystać z gotowców, zazwyczaj okazuje się, że ze względu na swoją uniwersalność, są zbyt „przegadane”. Tak samo było i tym razem. Prawie 20kB kodu udało mi się skrócić do kilkunastu linijek.

W skrócie trzeba zrobić tak:

  1. W JavaScript tworzysz normalną tablicę asocjacyjną z danymi formularza (nie będę wnikał, co Ci jest potrzebne) i zawartością pliku zamienioną na string funkcją btoa()
  2. Serializujesz tablicę do jednej zmiennej tekstowej
  3. Tworzysz obiekt XMLHttpRequest np. przy pomocy jQuery
  4. Wysyłasz dane jako obiekt JSON
  5. Po stronie serwera zamiast tablicy przesłanych danych $_POST$_FILES, masz tylko jedną, którą deserializujesz do tablicy
  6. Zawartość pliku dekodujesz przy pomocy base64_decode() i zapisujesz do pliku

To tak w skrócie. Pewnie opisałem to niezbyt klarownie, bo nie jestem teoretykiem programowania i nie znam tych wszystkich mądrych pojęć, którymi się posługujesz. Ale myślę, że wystarczy to jako punkt zaczepienia do dalszych poszukiwań, jeśli będzie Ci to potrzebne. W każdym razie zamiast bólu głowy mam kawałek dobrze działającego kodu.

Jeśli więc programujesz internety, to pamiętaj, że nie tylko MSIE lubi mijać się ze standardami. Najbardziej popularna przeglądarka na urządzenia od Apple również.

Jeśli podoba Ci się wpis,
koniecznie zalajkuj,
skomentuj i zapisz się na