I HTTP er der to måder at POST data på: application/x-wwwww-form-urlencoded
og multipart/form-data
. Jeg har forstået, at de fleste browsere kun kan uploade filer, hvis multipart/form-data
anvendes. Er der nogen yderligere vejledning om, hvornår man skal bruge en af kodningstyperne i en API-kontekst (ingen browser involveret)? Dette kunne f.eks. være baseret på:
Jeg har stort set ikke fundet nogen formel vejledning på nettet om brugen af de forskellige indholdstyper indtil videre.
TL;DR
Sammenfatning; hvis du har binære (ikke-alfanumeriske) data (eller en betydelig stor payload) at sende, skal du bruge multipart/form-data
. Ellers skal du bruge application/x-www-www-form-urlencoded
.
De MIME-typer, du nævner, er de to Content-Type
-headers for HTTP POST-forespørgsler, som user-agents (browsere) skal understøtte. Formålet med begge disse typer anmodninger er at sende en liste af navn/værdi-par til serveren. Afhængigt af typen og mængden af data, der sendes, vil en af metoderne være mere effektiv end den anden. For at forstå hvorfor, skal man se på, hvad de hver især gør under dække.
For application/x-www-www-form-urlencoded
er kroppen af den HTTP-meddelelse, der sendes til serveren, i det væsentlige én stor forespørgselsstreng -- navne/værdipar adskilles med et ampersand (&
), og navne adskilles fra værdier med ligningstegnet (=
). Et eksempel herpå er:
MinVariabelOne=VærdiOne&MinVariabelTwo=VærdiTwo
I henhold til [specifikationen] (http://www.w3.org/TR/html401/interact/forms.html):
[Reserveret og] ikke-alfanumeriske tegn erstattes af `%HH', et procenttegn og to hexadecimale cifre, der repræsenterer ASCII-koden for tegnet
Det betyder, at for hver ikke-alfanumerisk byte, der findes i en af vores værdier, vil det kræve tre bytes at repræsentere den. For store binære filer vil det være meget ineffektivt at tredoble nyttelasten.
Det er her multipart/form-data
kommer ind i billedet. Med denne metode til overførsel af navne/værdipar repræsenteres hvert par som en "part" i en MIME-meddelelse (som beskrevet i andre svar). Dele er adskilt af en bestemt strenggrænse (valgt specifikt således, at denne grænsestreng ikke forekommer i nogen af "value" payloads). Hver del har sit eget sæt af MIME-headere som Content-Type
og især Content-Disposition
, som kan give hver del sit "navn." Værdestykket i hvert navn/værdi-par er nyttelasten for hver del af MIME-meddelelsen. MIME-specifikationen giver os flere muligheder, når vi repræsenterer værdi-nyttelasten -- vi kan vælge en mere effektiv kodning af binære data for at spare båndbredde (f.eks. base 64 eller endda rå binær).
Hvorfor ikke bruge multipart/form-data
hele tiden? For korte alfanumeriske værdier (som de fleste webformularer) vil overheadet ved at tilføje alle MIME-headere i høj grad opveje besparelserne ved en mere effektiv binær kodning.
Jeg tror ikke, at HTTP er begrænset til POST i multipart eller x-www-form-urlencoded. Content-Type Header er ortogonal til HTTP POST-metoden (du kan udfylde den MIME-type, der passer dig). Dette er også tilfældet for typiske HTML-repræsentationsbaserede webapps (f.eks. blev json payload meget populær til at overføre payload til ajax-forespørgsler).
Med hensyn til Restful API over HTTP er de mest populære indholdstyper, som jeg kom i kontakt med, application/xml og application/json.
Jeg ville forsøge at repræsentere binære data som eget aktiv/ressource. Det tilføjer endnu et kald, men afkobler tingene bedre. Eksempel billeder:
POST /images
Content-type: multipart/mixed; boundary="xxxx"
... multipart-data
201 Oprettet
Placering: http://imageserver.org/../foo.jpg
I senere ressourcer kunne du blot inline den binære ressource som link:
Jeg er enig i meget af det, som Manuel har sagt. Faktisk henviser hans kommentarer til denne url...
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
... hvor der står:
Indholdstypen "application/x-www-form-urlencoded" er ineffektiv til at sende store mængder af binære data eller tekst der indeholder ikke-ASCII-tegn. indholdstype "multipart/form-data" bør anvendes til indsendelse af formularer der indeholder filer, ikke-ASCII-data, og binære data.
For mig ville det dog komme an på værktøjs-/rammeunderstøttelse.
Hvis du får et klart billede af dine brugere, og hvordan de vil bruge dit API, kan det hjælpe dig med at træffe en beslutning. Hvis du gør det svært for dine API-brugere at uploade filer, vil de flytte væk, eller du vil bruge en masse tid på at støtte dem.
Det sekundære aspekt er den værktøjsstøtte, DU har til at skrive din API, og hvor let det er for dig at tilpasse den ene uploadmekanisme frem for den anden.