HTTP sistemoje yra du duomenų siuntimo POST būdai: application/x-www-form-urlencoded
ir multipart/form-data
. Suprantu, kad dauguma naršyklių gali įkelti failus tik tada, kai naudojama multipart/form-data
. Ar yra kokių nors papildomų rekomendacijų, kada naudoti vieną iš kodavimo tipų API kontekste (be naršyklės)? Tai gali būti pagrįsta, pvz:
Internete iš esmės neradau jokių oficialių gairių dėl skirtingų turinio tipų naudojimo.
TL;DR
Apibendrinimas; jei norite perduoti dvejetainius (ne alfanumerinius) duomenis (arba didelės apimties krovinį), naudokite multipart/form-data
. Priešingu atveju naudokite application/x-www-form-urlencoded
.
MIME tipai, kuriuos minite, yra dvi HTTP POST užklausų Content-Type
antraštės, kurias turi palaikyti naudotojo agentai (naršyklės). Abiejų šių tipų užklausų tikslas - siųsti į serverį vardų ir verčių porų sąrašą. Priklausomai nuo siunčiamų duomenų tipo ir kiekio, vienas iš metodų bus efektyvesnis už kitą. Kad suprastumėte, kodėl, turite pažvelgti, ką kiekvienas iš jų daro po dangteliu.
Naudojant application/x-www-form-urlencoded
, HTTP pranešimo, siunčiamo į serverį, kūnas iš esmės yra viena didžiulė užklausos eilutė - vardų ir verčių poros atskiriamos ampersandu (&
), o vardai nuo verčių atskiriami lygybės simboliu (=
). Pavyzdys būtų toks:
MyVariableOne=VertėOne&MyVariableTwo=VertėTwo
Pagal [specifikaciją] (http://www.w3.org/TR/html401/interact/forms.html):
[Rezervuota ir] nealfanumeriniai simboliai pakeičiami `%HH', procento ženklu ir dviem šešioliktainiais skaitmenimis, reiškiančiais simbolio ASCII kodą
Tai reiškia, kad kiekvienam ne raidžių ir skaičių baitui, esančiam vienoje iš mūsų verčių, atvaizduoti prireiks trijų baitų. Dideliems dvejetainiams failams trigubinti naudingąjį krūvį bus labai neefektyvu.
Štai kur atsiranda multipart/form-data
. Naudojant šį vardų ir verčių porų perdavimo būdą, kiekviena pora pateikiama kaip "dalis" MIME pranešime (kaip aprašyta kituose atsakymuose). Dalys atskiriamos tam tikra ribine eilute (specialiai parinkta taip, kad šios ribinės eilutės nebūtų nė viename "vertės" krovinyje). Kiekviena dalis turi savo MIME antraščių rinkinį, pavyzdžiui, Content-Type
, ir ypač Content-Disposition
, kuris gali suteikti kiekvienai daliai "vardą"; Kiekvienos vardo ir vertės poros vertės dalis yra kiekvienos MIME pranešimo dalies naudingoji apkrova. MIME specifikacija suteikia mums daugiau galimybių atvaizduoti vertės naudingąją apkrovą - galime pasirinkti efektyvesnę dvejetainių duomenų koduotę, kad sutaupytume duomenų srauto pralaidumą (pvz., bazinę 64 arba net neapdorotą dvejetainę).
Kodėl ne visą laiką naudoti multipart/form-data
? Jei tai trumpos raidinės-skaitmeninės vertės (pvz., dauguma žiniatinklio formų), pridedant visas MIME antraštes patiriamos pridėtinės išlaidos bus daug didesnės už sutaupytas lėšas dėl efektyvesnio dvejetainio kodavimo.
Nemanau, kad HTTP apsiriboja tik POST daugiašale arba x-www-form-urlencoded. Antraštė Content-Type Header yra ortogonali HTTP POST metodui (galite užpildyti jums tinkamą MIME tipą). Taip yra ir tipinėse HTML atvaizdavimu pagrįstose žiniatinklio programose (pvz. json payload tapo labai populiarus perduodant ajax užklausų payload).
Kalbant apie Restful API per HTTP, populiariausi turinio tipai, su kuriais teko susidurti, yra application/xml ir application/json.
Bandyčiau dvejetainius duomenis pateikti kaip nuosavą turtą / išteklių. Tai prideda dar vieną skambutį, bet geriau atskiria dalykus. Paveikslėlių pavyzdys:
POST /images
Content-type: multipart/mixed; boundary="xxxx"
... multipart duomenys
201 Sukurta
Vieta: http://imageserver.org/../foo.jpg
Vėlesniuose ištekliuose galėtumėte tiesiog įterpti dvejetainį išteklių kaip nuorodą:
Sutinku su daugeliu Manuelio žodžių. Tiesą sakant, jo komentarai susiję su šiuo url adresu...
http://www.w3.org/TR/html401/interact/forms.html#h-17.13.4
... kuriame teigiama:
Turinio tipas "application/x-www-form-urlencoded" yra neefektyvus siunčiant didelius dvejetainių duomenų ar teksto kiekius kuriame yra ne ASCII simbolių. turinio tipas "multipart/form-data" turėtų būti naudojamas formoms siųsti kuriose yra failų, ne ASCII duomenų, ir dvejetainiai duomenys.
Tačiau man tai priklausytų nuo įrankių ir (arba) pagrindų palaikymo.
Jei aiškiai įsivaizduosite savo naudotojus ir tai, kaip jie naudosis jūsų API, tai padės jums apsispręsti. Jei API naudotojams bus sunku įkelti failus, jie pasitrauks, o jūs sugaišite daug laiko jiems palaikyti.
Antraeilis dalykas būtų tai, kokią paramą įrankiais jūs turite rašydami API ir kaip lengva jums pritaikyti vieną įkėlimo mechanizmą, o ne kitą.