एप्लिकेशन / x-www-form-urlencoded या मल्टीपार्ट / फॉर्म-डेटा?


1334

HTTP में POST डेटा के दो तरीके हैं: application/x-www-form-urlencodedऔर multipart/form-data। मैं समझता हूं कि अगर multipart/form-dataइस्तेमाल किया जाता है तो ज्यादातर ब्राउज़र केवल फाइलें अपलोड करने में सक्षम होते हैं । एपीआई संदर्भ (कोई ब्राउज़र शामिल नहीं) में एन्कोडिंग प्रकारों में से एक का उपयोग करते समय क्या कोई अतिरिक्त मार्गदर्शन है? यह उदाहरण के आधार पर हो सकता है:

  • डेटा का आकार
  • गैर- ASCII वर्णों का अस्तित्व
  • बाइनरी डेटा पर अस्तित्व (अनएन्कोडेड)
  • अतिरिक्त डेटा स्थानांतरित करने की आवश्यकता (जैसे फ़ाइल नाम)

मुझे मूल रूप से अब तक विभिन्न सामग्री-प्रकारों के उपयोग के बारे में वेब पर कोई औपचारिक मार्गदर्शन नहीं मिला।


74
यह उल्लेख किया जाना चाहिए कि ये दो MIME प्रकार हैं जिनका HTML रूप उपयोग करते हैं। HTTP में ही ऐसी कोई सीमा नहीं है ... कोई भी MIME प्रकार का उपयोग कर सकता है जो वह HTTP के माध्यम से चाहता है।
tybro0103

जवाबों:


2012

टी एल; डॉ

सारांश; यदि आपके पास संचारित करने, उपयोग करने के लिए बाइनरी (गैर-अल्फ़ान्यूमेरिक) डेटा (या काफी आकार का पेलोड) है multipart/form-data। अन्यथा, उपयोग करें application/x-www-form-urlencoded


आपके द्वारा उल्लिखित MIME प्रकार Content-TypeHTTP POST अनुरोधों के लिए दो शीर्षलेख हैं जो उपयोगकर्ता-एजेंटों (ब्राउज़रों) को समर्थन करना चाहिए। उन दोनों प्रकार के अनुरोधों का उद्देश्य सर्वर को नाम / मूल्य जोड़े की एक सूची भेजना है। टाइप किए जा रहे डेटा के प्रकार और मात्रा के आधार पर, तरीकों में से एक दूसरे की तुलना में अधिक कुशल होगा। यह समझने के लिए कि, आपको यह देखना होगा कि प्रत्येक कवर के नीचे क्या कर रहा है।

के लिए application/x-www-form-urlencoded, सर्वर के लिए भेजा HTTP संदेश के मुख्य भाग को अनिवार्य रूप से एक विशाल क्वेरी स्ट्रिंग है - नाम / मान युग्म एम्परसैंड (से अलग होते हैं &), और नाम मूल्यों से अलग होती है प्रतीक के बराबर होती है द्वारा ( =)। इसका एक उदाहरण यह होगा: 

MyVariableOne=ValueOne&MyVariableTwo=ValueTwo

विनिर्देश के अनुसार :

[आरक्षित और] गैर-अल्फ़ान्यूमेरिक वर्णों को '% HH' द्वारा बदल दिया जाता है, एक प्रतिशत चिन्ह और दो हेक्साडेसिमल अंक वर्ण के ASCII कोड का प्रतिनिधित्व करते हैं

इसका मतलब है कि प्रत्येक गैर-अल्फ़ान्यूमेरिक बाइट के लिए जो हमारे मूल्यों में से एक में मौजूद है, यह प्रतिनिधित्व करने के लिए तीन बाइट्स लेने जा रहा है। बड़ी द्विआधारी फ़ाइलों के लिए, पेलोड को तीन गुना करना अत्यधिक अक्षम है।

यही वह जगह है जहां multipart/form-dataनाम / मूल्य जोड़े को प्रसारित करने की इस पद्धति के साथ, प्रत्येक जोड़ी को MIME संदेश में "भाग" के रूप में दर्शाया जाता है (जैसा कि अन्य उत्तरों द्वारा वर्णित है)। भागों को एक विशेष स्ट्रिंग सीमा से अलग किया जाता है (विशेष रूप से चुना जाता है ताकि यह सीमा स्ट्रिंग "मूल्य" पेलोड में से किसी में न हो)। प्रत्येक भाग के पास MIME हेडर का अपना सेट होता है Content-Type, और विशेष रूप से Content-Disposition, जो प्रत्येक भाग को "नाम" दे सकता है। प्रत्येक नाम / मूल्य जोड़ी का मूल्य टुकड़ा MIME संदेश के प्रत्येक भाग का पेलोड है। MIME युक्ति हमें अधिक विकल्प देता है जब मूल्य पेलोड का प्रतिनिधित्व करते हैं - हम बैंडविड्थ को बचाने के लिए बाइनरी डेटा का एक अधिक कुशल एन्कोडिंग चुन सकते हैं (जैसे आधार 64 या कच्चा बाइनरी)।

multipart/form-dataहर समय उपयोग क्यों नहीं ? लघु अल्फ़ान्यूमेरिक मान (अधिकांश वेब फ़ॉर्म) के लिए, सभी MIME हेडर को जोड़ने का ओवरहेड अधिक कुशल बाइनरी एन्कोडिंग से किसी भी बचत को महत्वपूर्ण रूप से आगे बढ़ाने वाला है।


84
क्या x-www-form-urlencoded की लंबाई सीमा है या यह असीमित है?
पचेरियर

34
@Pacerier सीमा POST अनुरोध प्राप्त करने वाले सर्वर द्वारा लागू की जाती है। अधिक चर्चा के लिए इस सूत्र को देखें: stackoverflow.com/questions/2364840/…
मैट ब्रिज

5
@ZiggyTheHamster JSON और BSON विभिन्न प्रकार के डेटा के लिए प्रत्येक अधिक कुशल हैं। बेस 64 गज़िप से हीन है, दोनों क्रमबद्ध तरीकों के लिए। Base64 कोई भी लाभ नहीं लाता है, HTTP बाइनरी पेलोड का समर्थन करता है।
तिबरियू-आयनू स्टेन

16
यह भी ध्यान दें कि यदि किसी प्रपत्र में नामांकित फ़ाइल अपलोड है, तो आपकी एकमात्र पसंद फ़ॉर्म-डेटा है, क्योंकि urlencoded में फ़ाइल नाम रखने का कोई तरीका नहीं है (प्रपत्र-डेटा में यह सामग्री-वितरण के लिए नाम पैरामीटर है)।
गुइडो वैन रोसुम

4
@EML मेरे पैरेंटिकल को देखें "(विशेष रूप से चुना ताकि यह सीमा स्ट्रिंग" मूल्य "पेलोड) में से किसी में न हो"
मैट ब्रिजेस

151

सबसे पहले यहाँ पढ़ें!

मुझे पता है कि यह 3 साल बहुत देर हो चुकी है, लेकिन मैट का (स्वीकृत) उत्तर अपूर्ण है और अंततः आपको परेशानी में डाल देगा। यहां कुंजी यह है कि, यदि आप उपयोग multipart/form-dataकरना चुनते हैं , तो सीमा उस फ़ाइल डेटा में नहीं दिखाई देनी चाहिए जो सर्वर अंततः प्राप्त करता है।

यह कोई समस्या नहीं है application/x-www-form-urlencoded, क्योंकि कोई सीमा नहीं है। x-www-form-urlencodedहमेशा बाइनरी डेटा को संभाल सकते हैं, एक मध्यस्थ बाइट को तीन 7BITबाइट्स में बदलने के सरल समीक्षक द्वारा । अक्षम, लेकिन यह काम करता है (और ध्यान दें कि फाइलनाम के साथ-साथ बाइनरी डेटा को भेजने में सक्षम नहीं होने के बारे में टिप्पणी गलत है; आप बस इसे एक अन्य कुंजी / मूल्य जोड़ी के रूप में भेजें)।

इसके साथ समस्या multipart/form-dataयह है कि सीमा विभाजक फ़ाइल डेटा में मौजूद नहीं होना चाहिए (देखें RFC 2388 ; धारा 5.2 में उचित समुच्चय MIME प्रकार नहीं है, जो इस समस्या से बचा जाता है) के लिए एक लंगड़ा बहाना भी शामिल है।

तो, पहली नजर में, किसी भी फ़ाइल अपलोड, बाइनरी या अन्यथा multipart/form-dataमें कोई मूल्य नहीं है । आपने अपनी सीमा को नहीं चुनते हैं, तो आप करेंगे अंत में एक समस्या है, तो आप सादा पाठ या कच्चे द्विआधारी भेज रहे हैं कि क्या - सर्वर गलत जगह पर एक सीमा मिलेगा, और अपनी फ़ाइल छोटा कर दिया जाएगा, या पोस्ट असफल हो जायेगी।

कुंजी एक एन्कोडिंग और एक सीमा को चुनना है जैसे कि आपके चयनित सीमा वर्ण एन्कोडेड आउटपुट में प्रकट नहीं हो सकते। उपयोग करने के लिए एक सरल उपाय है base64( कच्चे बाइनरी का उपयोग करें)। में बेस 64 3 मनमाना बाइट्स चार 7 बिट वर्ण, जहां उत्पादन वर्ण सेट है में इनकोड [A-Za-z0-9+/=](यानी अक्षर या अंक, '+', '/' या '=')। =एक विशेष मामला है, और केवल एक =या दो के रूप में एन्कोडेड आउटपुट के अंत में दिखाई दे सकता है ==। अब, अपनी सीमा को 7-बिट ASCII स्ट्रिंग के रूप में चुनें जो base64आउटपुट में प्रकट नहीं हो सकता है । नेट पर आपके द्वारा देखे जाने वाले कई विकल्प इस परीक्षा में विफल हो जाते हैं - MDN डॉक्स बनाता है, उदाहरण के लिए, बाइनरी डेटा भेजते समय एक सीमा के रूप में "बूँद" का उपयोग करें - अच्छा नहीं। हालांकि, "बूँद!" base64आउटपुट में कभी नहीं दिखाई देगा ।


52
जबकि मल्टीपार्ट / फॉर्म-डेटा का एक विचार यह सुनिश्चित करता है कि सीमा डेटा में प्रकट नहीं होती है यह एक सीमा का चयन करके पूरा करने के लिए काफी सरल है जो पर्याप्त रूप से लंबा है। इसे पूरा करने के लिए कृपया हमें base64 एन्कोडिंग न दें। एक सीमा जो अनियमित रूप से उत्पन्न होती है और UUID की समान लंबाई पर्याप्त होनी चाहिए: stackoverflow.com/questions/1705008/…
जोशकोड्स

20
@EML, यह बिल्कुल समझ में नहीं आता है। जाहिर है कि सीमा को http क्लाइंट (ब्राउज़र) द्वारा स्वचालित रूप से चुना जाता है और क्लाइंट आपके द्वारा अपलोड की गई फ़ाइलों की सामग्री के साथ संघर्ष करने वाली सीमा का उपयोग नहीं करने के लिए पर्याप्त स्मार्ट होगा। यह उतना ही सरल है, जो एक मैचिंग मैच है index === -1
पचेरियर

13
@ स्पेसर: (ए) ने प्रश्न पढ़ा: "कोई ब्राउज़र शामिल नहीं, एपीआई संदर्भ"। (बी) ब्राउज़र वैसे भी आपके लिए अनुरोध का निर्माण नहीं करते हैं। आप इसे स्वयं करते हैं, मैन्युअल रूप से। ब्राउज़रों में कोई जादू नहीं है।
ईएमएल

12
@ बेनीबेला, वह शायद '()+-./:=तब उपयोग करने का सुझाव देने वाला है । फिर भी जाँच के विकल्प के साथ यादृच्छिक पीढ़ी अभी भी जाने का रास्ता है और इसे एक पंक्ति के साथ किया जा सकता है while(true){r = rand(); if(data.indexOf(r) === -1){doStuff();break;}}:। ईएमएल का सुझाव (बस मिलान से बचने के लिए बेस 64 में कनवर्ट करें) सिर्फ सादा अजीब है, यह उल्लेख करने के लिए नहीं कि यह अनावश्यक प्रदर्शन में गिरावट के साथ आता है। और एक लाइन एल्गोरिथ्म के बाद से कुछ भी नहीं के लिए सभी परेशानी समान रूप से सरल और सरल है। बेस 64 का मतलब इस तरह से इस्तेमाल (एब) नहीं है, क्योंकि HTTP बॉडी सभी 8-बिट ऑक्टेट्स को स्वीकार करती है
पचेरियर

31
यह जवाब न केवल चर्चा में शामिल करता है, बल्कि गलत सलाह भी देता है। सबसे पहले, जब भी अलग-अलग हिस्सों में यादृच्छिक डेटा संचारित करते हैं, तो यह हमेशा संभव होता है कि चुना हुआ सीमा पेलोड में मौजूद होगी। यह सुनिश्चित करने का एकमात्र तरीका यह नहीं है कि हम जिस सीमा के साथ आते हैं, उसके लिए पूरे पेलोड की जांच करें। पूरी तरह से अव्यावहारिक। हम बस टकराव की असीम संभावना को स्वीकार करते हैं और एक उचित सीमा के साथ आते हैं, जैसे "--- सीमा- <UUID यहाँ> -बाउंड्री ---"। दूसरे, हमेशा बेस 64 का उपयोग करने से बैंडविड्थ बर्बाद हो जाएगी और बिना किसी कारण के बफ़र्स भर जाएंगे।
योनि

92

मुझे नहीं लगता कि HTTP मल्टीपार्ट या x-www-form-urlencoded में POST तक सीमित है। सामग्री प्रकार हैडर HTTP POST विधि के लिए ओर्थोगोनल है (आप जो आप सूट MIME प्रकार भर सकते हैं)। यह भी विशिष्ट HTML प्रतिनिधित्व आधारित वेबएप्स के लिए मामला है (उदाहरण के लिए json पेलोड, अजाक्स अनुरोधों के लिए पेलोड को प्रेषित करने के लिए बहुत लोकप्रिय हो गया)।

HTTP पर रेस्टफुल एपीआई के संबंध में सबसे लोकप्रिय सामग्री-प्रकार जिनके साथ मैं संपर्क में आया, वे हैं एप्लीकेशन / एक्सएमएल और एप्लीकेशन / जसन।

application / xml:

  • डेटा-साइज़: XML बहुत वर्बोज़ है, लेकिन आमतौर पर संपीड़न और सोच का उपयोग करते समय एक मुद्दा नहीं है कि लिखने का उपयोग मामला (जैसे कि POST या PUT के माध्यम से) रीड-एक्सेस के रूप में बहुत अधिक दुर्लभ है (कई मामलों में यह सभी ट्रैफ़िक का 3% है) )। शायद ही कभी ऐसे मामले होते हैं जहाँ मुझे लेखन प्रदर्शन का अनुकूलन करना पड़ता था
  • गैर-एससीआई चर का अस्तित्व: आप XML में एन्कोडिंग के रूप में utf-8 का उपयोग कर सकते हैं
  • द्विआधारी डेटा के अस्तित्व: base64 एन्कोडिंग का उपयोग करने की आवश्यकता होगी
  • फ़ाइल नाम डेटा: आप इसे XML के अंदर फ़ील्ड में एन्क्रिप्ट कर सकते हैं

आवेदन / json

  • डेटा-आकार: अधिक कॉम्पैक्ट कम एक्सएमएल, फिर भी पाठ, लेकिन आप संपीड़ित कर सकते हैं
  • गैर-अस्की चरस: json utf-8 है
  • द्विआधारी डेटा: base64 (जन्स बाइनरी-प्रश्न भी देखें )
  • फ़ाइल नाम डेटा: json के अंदर फ़ील्ड-सेक्शन के रूप में इनकैप्सुलेट करता है

स्वयं के संसाधन के रूप में द्विआधारी डेटा

मैं बाइनरी डेटा को अपनी संपत्ति / संसाधन के रूप में दर्शाने की कोशिश करूंगा। यह एक और कॉल जोड़ता है लेकिन सामान को बेहतर तरीके से डिकॉय करता है। उदाहरण चित्र:

POST /images
Content-type: multipart/mixed; boundary="xxxx" 
... multipart data

201 Created
Location: http://imageserver.org/../foo.jpg  

बाद के संसाधनों में आप केवल बाइनरी संसाधन को लिंक के रूप में इनलाइन कर सकते हैं:

<main-resource>
 ...
 <link href="http://imageserver.org/../foo.jpg"/>
</main-resource>

दिलचस्प। लेकिन एप्लिकेशन / x-www-form-urlencoded का उपयोग कब करें और कब मल्टीपार्ट / फॉर्म-डेटा का उपयोग करें?
अधिकतम

3
एप्लिकेशन / x-www-form-urlencoded आपके अनुरोध का डिफ़ॉल्ट माइम-प्रकार है (यह भी देखें w3.org/TR/html401/interact/forms.html#h-17.13.4 )। मैं इसे "सामान्य" वेबफॉर्म के लिए उपयोग करता हूं। API के लिए मैं एप्लिकेशन / xml | json का उपयोग करता हूं। मल्टीपार्ट / फॉर्म-डेटा अटेचमेंट्स की सोच में एक घंटी है (प्रतिक्रिया शरीर के अंदर कई डेटा-सेक्शन को एक परिभाषित सीमा स्ट्रिंग के साथ समतल किया जाता है)।
मैनुअल अलादाना

4
मुझे लगता है कि ओपी शायद उन दो प्रकारों के बारे में पूछ रहा था जो एचटीएमएल रूपों का उपयोग करते हैं, लेकिन मुझे खुशी है कि यह इंगित किया गया था।
tybro0103

30

मैं इस बात से सहमत हूं कि मैनुअल ने कहा है। वास्तव में, उनकी टिप्पणी इस url को संदर्भित करती है ...

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

... कौन सा राज्य:

सामग्री प्रकार "एप्लिकेशन / x-www-form-urlencoded" बाइनरी डेटा या गैर-ASCII वर्णों वाले पाठ को बड़ी मात्रा में भेजने के लिए अक्षम है। सामग्री प्रकार "मल्टीपार्ट / फॉर्म-डेटा" का उपयोग उन प्रपत्रों को प्रस्तुत करने के लिए किया जाना चाहिए जिनमें फाइलें, गैर-एएससीआईआई डेटा और बाइनरी डेटा शामिल हैं।

हालाँकि, मेरे लिए यह टूल / फ्रेमवर्क सपोर्ट के लिए नीचे आएगा।

  • आप कौन से टूल और फ्रेमवर्क की अपेक्षा करते हैं, जिससे आपके एपीआई उपयोगकर्ता अपने ऐप्स का निर्माण कर सकें?
  • क्या उनके पास ढांचा या घटक हैं जो वे उस विधि का उपयोग दूसरे पर कर सकते हैं?

यदि आपको अपने उपयोगकर्ताओं के बारे में स्पष्ट जानकारी मिलती है, और वे आपके एपीआई का उपयोग कैसे करेंगे, तो इससे आपको निर्णय लेने में मदद मिलेगी। यदि आप अपने एपीआई उपयोगकर्ताओं के लिए फ़ाइलों के अपलोड को कठिन बनाते हैं, तो वे दूर चले जाएंगे, आप उनका समर्थन करने में बहुत समय बिताएंगे।

इसके लिए द्वितीयक वह टूल सपोर्ट होगा जो आपके पास आपके एपीआई को लिखने के लिए है और आपके लिए दूसरे पर एक अपलोड तंत्र को समायोजित करना कितना आसान है।


1
नमस्ते, क्या इसका मतलब यह है कि हर बार जब हम वेब सर्वर पर कुछ पोस्ट करते हैं, तो हमें यह उल्लेख करना होगा कि वेब सर्वर को यह बताने के लिए कि सामग्री-प्रकार क्या है? यहां तक ​​कि हम http के अनुरोध को स्वयं तैयार करते हैं, हमें सामग्री-प्रकार का सही उल्लेख करना चाहिए?
GMsoF

2
@GMsoF, यह वैकल्पिक है। Stackoverflow.com/a/16693884/632951 देखें । जब आप जेनेरिक ओवरहेड्स से बचने के लिए किसी विशिष्ट सर्वर के लिए एक विशिष्ट अनुरोध को तैयार करते हैं तो आप सामग्री-प्रकार का उपयोग करने से बचना चाह सकते हैं।
पचेरियर

2

HTML5 कैनवास छवि डेटा अपलोड करने के लिए मेरी ओर से बस थोड़ा सा संकेत:

मैं एक प्रिंट-शॉप के लिए एक परियोजना पर काम कर रहा हूं और HTML5 canvasतत्व से आए सर्वर पर चित्र अपलोड करने के कारण कुछ समस्याएं थीं । मैं कम से कम एक घंटे के लिए संघर्ष कर रहा था और मुझे अपने सर्वर पर छवि को सही ढंग से सहेजने के लिए नहीं मिला।

एक बार जब मैंने contentTypeअपने jQuery के ajax कॉल का विकल्प सेट किया तो application/x-www-form-urlencodedसब कुछ सही तरीके से हो गया और बेस 64-एन्कोडेड डेटा को सही ढंग से व्याख्या किया गया और सफलतापूर्वक एक छवि के रूप में सहेजा गया।


शायद यह किसी की मदद करता है!


4
आपके द्वारा इसे बदलने से पहले यह किस प्रकार की सामग्री भेज रहा था? यह समस्या सर्वर द्वारा उस सामग्री प्रकार का समर्थन नहीं करने के कारण हो सकती है जो आप इसे भेज रहे थे।
कैटॉर्डा

1

यदि आपको सामग्री-प्रकार = x-www-urlencoded-form का उपयोग करने की आवश्यकता है, तो पैरामीटर के रूप में FormDataCollection का उपयोग न करें: asp.net Core 2+ FormDataCollection में कोई डिफ़ॉल्ट निर्माता नहीं है, जो फ़ॉर्मेटर द्वारा आवश्यक है। इसके बजाय IFormCollection का उपयोग करें:

 public IActionResult Search([FromForm]IFormCollection type)
    {
        return Ok();
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.