CZYTAJ CO NAJMNIEJ PIERWSZĄ PARĘ TUTAJ!
Wiem, że to 3 lata za późno, ale odpowiedź Matta (zaakceptowana) jest niekompletna i ostatecznie wpakuje cię w kłopoty. Kluczem tutaj jest to, że jeśli zdecydujesz się użyć multipart/form-data
, granica nie może pojawić się w danych pliku, które serwer ostatecznie otrzyma.
Nie stanowi to problemu application/x-www-form-urlencoded
, ponieważ nie ma granicy. x-www-form-urlencoded
może również zawsze obsługiwać dane binarne, po prostu zamieniając jeden dowolny bajt na trzy 7BIT
bajty. Nieefektywne, ale działa (i zauważ, że komentarz o niemożności wysyłania nazw plików oraz danych binarnych jest niepoprawny; po prostu wysyłasz go jako inną parę klucz / wartość).
Problem multipart/form-data
polega na tym, że separator granic nie może być obecny w danych pliku (patrz RFC 2388 ; sekcja 5.2 zawiera również dość kiepską wymówkę, że nie ma odpowiedniego zagregowanego typu MIME, który pozwala uniknąć tego problemu).
Tak, na pierwszy rzut oka, multipart/form-data
nie ma żadnej wartości w ogóle w jakikolwiek przesłanie pliku, binarny lub inaczej. Jeśli nie wybierzesz poprawnie granicy, w końcu będziesz mieć problem, niezależnie od tego, czy wysyłasz zwykły tekst, czy surowy plik binarny - serwer znajdzie granicę w niewłaściwym miejscu, a plik zostanie obcięty lub test POST zawiedzie.
Kluczem jest wybranie kodowania i granicy, tak aby wybrane znaki graniczne nie mogły pojawić się w zakodowanym wyjściu. Jednym prostym rozwiązaniem jest użycie base64
( nie używaj surowego pliku binarnego). W base64 3 dowolne bajty są zakodowane w czterech 7-bitowych znakach, gdzie wyjściowy zestaw znaków to [A-Za-z0-9+/=]
(tj. Alfanumeryczny, „+”, „/” lub „=”). =
jest szczególnym przypadkiem i może pojawić się tylko na końcu zakodowanego wyjścia jako pojedynczy =
lub podwójny ==
. Teraz wybierz swoją granicę jako 7-bitowy ciąg ASCII, który nie może pojawić się na base64
wyjściu. Wiele wyborów, które widzisz w sieci, nie spełnia tego testu - MDN tworzy dokumenty, na przykład użyj „obiektu blob” jako granicy podczas wysyłania danych binarnych - źle. Jednak coś takiego jak „! Blob!” nigdy nie pojawi się na base64
wyjściu.