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:
Jak dotąd nie znalazłem w sieci żadnych formalnych wytycznych dotyczących stosowania różnych typów zawartości.
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.
Nie sądzę, że HTTP jest ograniczony do POST w multipart lub x-www-form-urlencoded. Nagłówek Content-Type 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.
Spróbowałbym reprezentować dane binarne jako własny zasób / zasób. Dodaje to kolejne połączenie, ale oddziela rzeczy lepiej. Przykładowe obrazy:
POST /images
Content-type: multipart/mixed; boundary="xxxx"
... dane wieloczęściowe
201 Utworzono
Lokalizacja: http://imageserver.org/../foo.jpg
W późniejszych zasobach mógłbyś po prostu inline'ować zasoby binarne jako link:
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.
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.