application/x-www-form-urlencoded lub multipart/form-data?

W HTTP są dwa sposoby na POST danych: application/x-www-form-urlencoded i multipart/form-data. Rozumiem, że większość przeglądarek jest w stanie przesyłać pliki tylko wtedy, gdy multipart/form-data jest używane. Czy są jakieś dodatkowe wskazówki kiedy używać jednego z typów kodowania w kontekście API (bez udziału przeglądarki)? Może to być np. oparte na:

  • rozmiar danych
  • występowanie znaków innych niż ASCII
  • istnienie (niezakodowanych) danych binarnych
  • konieczność przesłania dodatkowych danych (jak nazwa pliku)

Jak dotąd nie znalazłem w sieci żadnych formalnych wytycznych dotyczących stosowania różnych typów zawartości.

Rozwiązanie

TL;DR

Podsumowanie; jeśli masz binarne (niealfanumeryczne) dane (lub znacznej wielkości ładunek) do przesłania, użyj multipart/form-data. W przeciwnym razie, użyj application/x-www-form-urlencoded.


Typy MIME, o których wspominasz to dwa nagłówki Content-Type dla żądań HTTP POST, które muszą być obsługiwane przez agentów użytkownika (przeglądarki). Celem obu tych typów żądań jest wysłanie listy par nazwa/wartość do serwera. W zależności od rodzaju i ilości przesyłanych danych, jedna z metod będzie bardziej wydajna niż druga. Aby zrozumieć dlaczego, musisz spojrzeć na to, co każda z nich robi pod przykrywką.

Dla application/x-www-form-urlencoded, treść wiadomości HTTP wysyłanej do serwera jest w zasadzie jednym wielkim ciągiem zapytania -- pary nazwa/wartość są oddzielone ampersandem (&), a nazwy są oddzielone od wartości symbolem równości (=). Przykładem tego może być: 

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo.

Zgodnie ze specyfikacją:

Znaki niealfanumeryczne są zastępowane przez `%HH', znak procentu i dwie cyfry szesnastkowe reprezentujące kod ASCII znaku.

Oznacza to, że dla każdego niealfanumerycznego bajtu, który istnieje w jednej z naszych wartości, potrzeba trzech bajtów do jego reprezentacji. Dla dużych plików binarnych, potrojenie ładunku będzie wysoce nieefektywne.

W tym miejscu z pomocą przychodzi multipart/form-data. Z tą metodą przesyłania par nazwa/wartość, każda para jest reprezentowana jako "część" w wiadomości MIME (jak opisano w innych odpowiedziach). Części są oddzielone określonym łańcuchem granicznym (wybranym specjalnie tak, aby ten ciąg graniczny nie występował w żadnym z "wartości" payloads). Każda część ma swój własny zestaw nagłówków MIME, takich jak Content-Type, a zwłaszcza Content-Disposition, które mogą nadać każdej części jej "nazwę." Wartość każdej pary nazwa-wartość jest ładunkiem każdej części wiadomości MIME. Specyfikacja MIME daje nam więcej opcji podczas reprezentowania wartości - możemy wybrać bardziej wydajne kodowanie danych binarnych, aby zaoszczędzić przepustowość (np. base 64 lub nawet raw binary).

Dlaczego nie używać multipart/form-data przez cały czas? Dla krótkich wartości alfanumerycznych (jak większość formularzy internetowych), narzut dodawania wszystkich nagłówków MIME będzie znacznie przewyższał jakiekolwiek oszczędności z bardziej wydajnego kodowania binarnego.

Komentarze (16)

Nie sądzę, że HTTP jest ograniczony do POST w multipart lub x-www-form-urlencoded. Nagłówek [Content-Type][1] jest ortogonalny do metody HTTP POST (możesz wypełnić typ MIME, który ci odpowiada). Tak jest również w przypadku typowych webapps opartych na reprezentacji HTML (np. json payload stał się bardzo popularny do przekazywania payload dla żądań ajaxowych).

Jeśli chodzi o Restful API po HTTP, najpopularniejsze typy zawartości z jakimi miałem styczność to application/xml oraz application/json.

application/xml:

  • data-size: XML bardzo verbose, ale zazwyczaj nie stanowi to problemu, gdy zastosuje się kompresję i pomyśli, że przypadek dostępu do zapisu (np. poprzez POST lub PUT) jest znacznie rzadszy niż do odczytu (w wielu przypadkach jest to
Komentarze (3)

Zgadzam się z tym, co powiedział Manuel. W rzeczywistości jego uwagi odnoszą się do tego adresu url...

http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4

... który mówi:

Typ zawartości. "application/x-www-form-urlencoded" jest nieefektywny do wysyłania dużych ilości danych binarnych lub tekstu zawierającego znaki inne niż ASCII. Adres typ zawartości "multipart/form-data" powinien być używany do przesyłania formularzy które zawierają pliki, dane nie będące znakami ASCII, oraz dane binarne.

Jednak dla mnie sprowadziłoby się to do wsparcia narzędzia / pracy.

  • Jakie narzędzia i frameworki oczekujesz, że użytkownicy API będą budować swoje aplikacje?
  • Czy mają oni frameworki lub komponenty, których mogą używać które faworyzują jedną metodę nad innymi?

Jeśli masz jasne wyobrażenie o swoich użytkowników, i jak oni'll korzystać z API, a następnie, że pomoże Ci zdecydować. Jeśli zrobisz przesyłanie plików trudne dla użytkowników API wtedy oni'll przenieść się, z you'll spędzić dużo czasu na wspieranie ich.

Wtórnie do tego byłoby wsparcie narzędzia masz do pisania API i jak łatwo jest dla Ciebie, aby pomieścić jeden mechanizm przesyłania nad innymi.

Komentarze (2)