Odpowiedzi:
Kiedy składasz żądanie POST, musisz w pewien sposób zakodować dane, które składają się na treść żądania.
Formularze HTML zapewniają trzy metody kodowania.
application/x-www-form-urlencoded (domyślny)multipart/form-datatext/plainTrwają prace nad dodaniem application/json, ale zostało to porzucone.
(Możliwe są inne kodowania w przypadku żądań HTTP generowanych przy użyciu innych środków niż przesyłanie formularza HTML. JSON jest popularnym formatem do użytku z usługami internetowymi, a niektóre nadal używają SOAP.)
Specyfika formatów nie ma znaczenia dla większości programistów. Ważne punkty to:
text/plain.Podczas pisania kodu po stronie klienta:
multipart/form-datagdy formularz zawiera jakiekolwiek <input type="file">elementymultipart/form-datalub, application/x-www-form-urlencodedale application/x-www-form-urlencodedbędzie bardziej wydajnyPodczas pisania kodu po stronie serwera:
Większość (jak Perl CGI->paramlub ten ujawniony przez $_POSTsuperglobal PHP ) zajmie się różnicami. Nie przejmuj się próbą przetworzenia nieprzetworzonych danych wejściowych otrzymanych przez serwer.
Czasami znajdziesz bibliotekę, która nie obsługuje obu formatów. Najpopularniejszą biblioteką Node.js do obsługi danych formularzy jest body-parser, który nie może obsłużyć żądań wieloczęściowych (ale ma dokumentację, która zaleca pewne alternatywy, które mogą).
Jeśli piszesz (lub debugujesz) bibliotekę do analizowania lub generowania surowych danych, musisz zacząć martwić się o format. Możesz także chcieć o tym wiedzieć ze względu na zainteresowanie.
application/x-www-form-urlencoded jest mniej więcej taki sam jak ciąg zapytania na końcu adresu URL.
multipart/form-datajest znacznie bardziej skomplikowany, ale pozwala na włączenie całych plików do danych. Przykład wyniku można znaleźć w specyfikacji HTML 4 .
text/plainjest wprowadzony przez HTML 5 i jest użyteczny tylko do debugowania - ze specyfikacji : Nie są one niezawodnie interpretowalne przez komputer - i twierdzę, że inne w połączeniu z narzędziami (takimi jak Panel sieci w narzędziach programistycznych większości przeglądarek) są lepsze za to).
kiedy powinniśmy go użyć
Odpowiedź Quentina jest prawidłowa: użyj, multipart/form-datajeśli formularz zawiera przesyłanie pliku, a w application/x-www-form-urlencodedprzeciwnym razie, co jest domyślne, jeśli pominiesz enctype.
Zamierzam:
Istnieją trzy możliwości dla enctype:
application/x-www-form-urlencodedmultipart/form-data(spec wskazuje na RFC7578 )text/plain. Nie jest to „niezawodnie interpretowalne przez komputer”, więc nigdy nie powinno się go stosować w produkcji i nie będziemy się temu zagłębiać.Gdy zobaczysz przykład każdej metody, staje się oczywiste, jak działają i kiedy powinieneś użyć każdej z nich.
Możesz tworzyć przykłady, używając:
nc -llub serwer ECHO: serwer testowy HTTP akceptuje żądania GET / POSTZapisz formularz do minimalnego .htmlpliku:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
<title>upload</title>
</head>
<body>
<form action="http://localhost:8000" method="post" enctype="multipart/form-data">
<p><input type="text" name="text1" value="text default">
<p><input type="text" name="text2" value="aωb">
<p><input type="file" name="file1">
<p><input type="file" name="file2">
<p><input type="file" name="file3">
<p><button type="submit">Submit</button>
</form>
</body>
</html>
Ustawiamy domyślną wartość tekstową na aωb, co oznacza, aωbże ωjest U+03C9, czyli bajtów 61 CF 89 62w UTF-8.
Utwórz pliki do przesłania:
echo 'Content of a.txt.' > a.txt
echo '<!DOCTYPE html><title>Content of a.html.</title>' > a.html
# Binary file containing 4 bytes: 'a', 1, 2 and 'b'.
printf 'a\xCF\x89b' > binary
Uruchom nasz mały serwer echa:
while true; do printf '' | nc -l 8000 localhost; done
Otwórz HTML w przeglądarce, wybierz pliki, kliknij prześlij i sprawdź terminal.
nc drukuje otrzymane żądanie.
Testowane na: Ubuntu 14.04.3, ncBSD 1.105, Firefox 40.
Firefox wysłał:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150
Content-Length: 834
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text1"
text default
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="text2"
aωb
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file1"; filename="a.txt"
Content-Type: text/plain
Content of a.txt.
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file2"; filename="a.html"
Content-Type: text/html
<!DOCTYPE html><title>Content of a.html.</title>
-----------------------------735323031399963166993862150
Content-Disposition: form-data; name="file3"; filename="binary"
Content-Type: application/octet-stream
aωb
-----------------------------735323031399963166993862150--
W przypadku pliku binarnego i pola tekstowego bajty 61 CF 89 62( aωbw UTF-8) są wysyłane dosłownie. Możesz to sprawdzić za pomocą nc -l localhost 8000 | hd, co oznacza, że bajty:
61 CF 89 62
zostały wysłane ( 61== 'a' i 62== 'b').
Dlatego jasne jest, że:
Content-Type: multipart/form-data; boundary=---------------------------735323031399963166993862150ustawia typ zawartości na multipart/form-datai mówi, że pola są oddzielone danym boundaryciągiem.
Pamiętaj jednak, że:
boundary=---------------------------735323031399963166993862150
ma dwa mniej ojców --niż rzeczywista bariera
-----------------------------735323031399963166993862150
Wynika to z faktu, że norma wymaga, aby granica zaczynała się od dwóch myślników --. Inne myślniki wydają się być tym, w jaki sposób Firefox wybrał implementację arbitralnej granicy. RFC 7578 wyraźnie wspomina, że te dwa wiodące myślniki --są wymagane:
4.1 „Boundary” Parametr danych wieloczęściowych / formularzy
Podobnie jak w przypadku innych typów wieloczęściowych, części są rozdzielane ogranicznikiem granicy, konstruowanym przy użyciu CRLF, „-” i wartości parametru „granicy”.
Każde pole dostaje kilka nagłówków podrzędnych przed jego danych: Content-Disposition: form-data;pole name, tym filename, po której następuje danych.
Serwer odczytuje dane do następnego ciągu granicznego. Przeglądarka musi wybrać granicę, która nie pojawi się w żadnym z pól, dlatego granica może się różnić w zależności od żądania.
Ponieważ mamy unikalną granicę, kodowanie danych nie jest konieczne: dane binarne są wysyłane w niezmienionej postaci.
DO ZROBIENIA: jaki jest optymalny rozmiar granicy ( log(N)założę się) i nazwa / czas działania algorytmu, który ją znajduje? Pytanie zadane na: /cs/39687/find-the-shortest-sequence-that-is-not-a-sub-sequence-of-a-set-of-sequences
Content-Type jest automatycznie określany przez przeglądarkę.
Jak to dokładnie ustalić, zapytano na stronie: W jaki sposób typ MIME przesłanego pliku jest określany przez przeglądarkę?
Teraz zmienić enctypesię application/x-www-form-urlencoded, załaduj przeglądarkę, i ponownie.
Firefox wysłał:
POST / HTTP/1.1
[[ Less interesting headers ... ]]
Content-Type: application/x-www-form-urlencoded
Content-Length: 51
text1=text+default&text2=a%CF%89b&file1=a.txt&file2=a.html&file3=binary
Najwyraźniej dane pliku nie zostały wysłane, tylko nazwy basename. Nie można tego użyć do plików.
Co do pola tekstowego, widzimy, że zwykłe znaki druku jak ai bwysłano w jednym bajcie, a niedrukowalne te, jak 0xCFi 0x89zajął 3 bajty każda: %CF%89!
Przesyłane pliki często zawierają wiele znaków niedrukowalnych (np. Obrazy), podczas gdy formularze tekstowe prawie nigdy tego nie robią.
Z przykładów, które widzieliśmy, że:
multipart/form-data: dodaje do wiadomości kilka bajtów narzutu granicznego i musi poświęcić trochę czasu na jego obliczenie, ale wysyła każdy bajt w jednym bajcie.
application/x-www-form-urlencoded: ma granicę jednego bajtu na pole ( &), ale dodaje liniowy współczynnik obciążenia 3x dla każdego znaku, który nie może być wydrukowany.
Dlatego nawet gdybyśmy mogli przesyłać pliki application/x-www-form-urlencoded, nie chcielibyśmy, ponieważ jest to tak nieefektywne.
Ale w przypadku znaków drukowalnych znalezionych w polach tekstowych nie ma to znaczenia i generuje mniejszy narzut, więc po prostu go używamy.
%CFjest długa: 3 bajty %, Ca F:-) Historia czyni go czytelny dla człowieka.
ncnie będzie akceptować zarówno -li te -pargumenty jednocześnie. Ale to działa na mnie while true; do printf '' | nc -l 8000; done.
Content-Typema dwa łączniki ( --) mniej, tzn. Kiedy faktycznie używasz granicy w treści wiadomości, musisz ją poprzedzić --. Ostatnią granicę należy także uzupełnić --, ale łatwo to zauważyć. Zobacz stackoverflow.com/questions/3508252/…
enctype='multipart/form-datajest typem kodowania, który umożliwia wysyłanie plików za pomocą POST . Po prostu bez tego kodowania pliki nie mogą być wysyłane przez POST .
Jeśli chcesz zezwolić użytkownikowi na przesyłanie pliku za pomocą formularza, musisz użyć tego typu .
multipart/form-datado wysyłania plików niebinarnych, ale jest to nieefektywne. Wydaje mi się, że używanie application/x-www-form-urlencodedjest poprawnym sposobem wysyłania danych niebinarnych, ale ktoś z większym doświadczeniem z plikami niebinarnymi może potrzebować mnie poprawić.
multipart/form-datado wysyłania pliku jest to, że będzie on działał automatycznie zarówno w interfejsie użytkownika, jak i w interfejsie użytkownika. Nie musisz wykonywać żadnych specjalnych czynności. Wszystkie pliki są binarne, nawet jeśli powinny zawierać tylko tekst. application/x-www-form-urlencodedjest standardowym sposobem POST formularza bez załączonych plików. multipart/form-datajest standardowym sposobem POST formularza z załączonymi plikami. (Istnieje również wiele innych kodowań, takich jak application/jsoni application/json-patch+json, które są wspólne dla komunikacji między serwerem a klientem.)
multipart/form-data. Czego nie może zrobić, to zrobić za pomocą zwykłego przesyłanie formularza HTML, bez JavaScriptu. Ustawienie formularza do użycia multipart/form-datajest jedynym mechanizmem zapewnianym przez HTML, który umożliwia pliki POST bez użycia JavaScript. Wydaje mi się, że nie jest to wystarczająco jasne w odpowiedzi i naiwny czytelnik może pomyśleć, że niemożność przesłania plików bez multipart/form-dataograniczeń jest ograniczeniem HTTP ; nie o to chodzi.
Przesyłając formularz, powiadamiasz przeglądarkę, aby wysłała za pośrednictwem protokołu HTTP wiadomość w sieci, odpowiednio umieszczoną w strukturze wiadomości protokołu TCP / IP. Strona HTML ma sposób na przesłanie danych do serwera: za pomocą <form>s.
Po przesłaniu formularza tworzone jest żądanie HTTP i wysyłane do serwera, wiadomość będzie zawierać nazwy pól w formularzu i wartości wypełnione przez użytkownika. Ta transmisja może się zdarzyć z POSTlub GET metod HTTP .
POST mówi przeglądarce, aby zbudowała wiadomość HTTP i umieściła całą treść w treści wiadomości (bardzo przydatny sposób robienia rzeczy, bardziej bezpieczny i elastyczny).GETprześle dane formularza w zapytaniu . Ma pewne ograniczenia dotyczące reprezentacji danych i długości.Atrybut enctypema sens tylko przy użyciu POSTmetody. Jeśli jest określony, instruuje przeglądarkę, aby wysłała formularz, kodując jego zawartość w określony sposób. Z MDN - typ formularza :
Gdy wartością atrybutu metody jest post, kodem jest typ MIME treści, która jest używana do przesłania formularza na serwer.
application/x-www-form-urlencoded: To jest ustawienie domyślne. Kiedy formularz jest wysyłany, wszystkie nazwy i wartości są gromadzone, a kodowanie adresu URL jest wykonywane na końcowym ciągu.multipart/form-data: Znaki NIE są kodowane. Jest to ważne, gdy formularz ma kontrolę przesyłania plików. Chcesz wysłać plik binarny, co zapewni, że strumień bitów nie zostanie zmieniony.text/plain: Spacje są konwertowane, ale kodowanie nie jest wykonywane.Podczas przesyłania formularzy mogą pojawić się pewne obawy dotyczące bezpieczeństwa, jak podano w RFC 7578 Sekcja 7: Wieloczęściowe dane formularza - Względy bezpieczeństwa :
Każde oprogramowanie do przetwarzania formularzy powinno traktować dane formularzy dostarczone przez użytkownika
z wrażliwością, ponieważ często zawierają informacje poufne lub umożliwiające
identyfikację użytkownika. W przeglądarkach internetowych powszechnie stosuje się funkcje automatycznego wypełniania formularzy; mogą one zostać wykorzystane do nakłonienia użytkowników do
nieświadomego wysłania poufnych informacji podczas wykonywania w inny sposób
nieszkodliwych zadań. dane wieloczęściowe / formularze nie zapewniają żadnych funkcji
sprawdzania integralności, zapewniania poufności, unikania
pomyłek użytkowników lub innych funkcji bezpieczeństwa; obawami tymi muszą się
zająć aplikacje do wypełniania formularzy i interpretacji danych.Aplikacje, które otrzymują formularze i przetwarzają je, muszą uważać, aby nie dostarczyć danych z powrotem do żądającej strony przetwarzającej formularze, która nie była przeznaczona do wysłania.
Ważne jest, aby interpretować nazwę pliku w
polu nagłówka Content- Disposition, aby nieumyślnie nadpisać pliki w obszarze plików
odbiorcy.
Dotyczy to Ciebie, jeśli jesteś programistą, a Twój serwer będzie przetwarzał formularze przesłane przez użytkowników, które mogą ostatecznie zawierać poufne informacje.
enctyperobimy. Wiem, że to dosłownie z multipart/form-dataRFC, ale mimo to jest to arbitralny zrzut względów bezpieczeństwa dotyczących przesyłania formularzy, które są całkowicie ortogonalne względem tego, czy dane są wysyłane jako application/x-www-form-urlencodedczy multipart/form-data.
Ustaw atrybut metody na POST, ponieważ zawartości pliku nie można umieścić w parametrze URL za pomocą formularza.
Ustaw wartość typu kodowania na wieloczęściowe / dane formularza, ponieważ dane zostaną podzielone na wiele części, po jednej dla każdego pliku plus jedna dla tekstu treści formularza, który można z nimi wysłać.
POSTto, że prawdopodobnie wystarczy przesłanie pliku za pomocą formularza, a dodanie multipart/form-datajest jedynie premią w jakiś niejasny sposób. Nie o to chodzi. Większość plików będzie absolutnie wymagać użycia multipart/form-data.
<head>i <body>jest nieistotne i mylące.
Zwykle dzieje się tak, gdy masz formularz POST, który wymaga przesłania pliku jako danych ... powie to serwerowi, w jaki sposób koduje przesyłane dane, w takim przypadku nie zostanie zakodowany, ponieważ po prostu przesyła i przesyła pliki na serwer, na przykład podczas przesyłania obrazu lub pliku pdf
Atrybut enctype określa, w jaki sposób dane formularza powinny być kodowane podczas przesyłania ich na serwer.
Atrybutu enctype można użyć tylko wtedy, gdy method = "post".
Żadne znaki nie są kodowane. Ta wartość jest wymagana, gdy używasz formularzy, które mają kontrolę przesyłania plików
Od W3Schools
multipart/form-data. Jest to również dość niejasne; co w ogóle oznacza zdanie „Żadne znaki nie są kodowane”? -1.