मैं C # में काम कर रहा हूं और 2 ऐप्स के बीच कुछ संचार कर रहा हूं जो मैं लिख रहा हूं। मुझे वेब एपीआई और JSON पसंद आया है। अब मैं उस बिंदु पर हूं जहां मैं दो सर्वरों के बीच एक रिकॉर्ड भेजने के लिए एक नियमित लिख रहा हूं जिसमें कुछ पाठ डेटा और एक फ़ाइल शामिल है।
इंटरनेट के अनुसार मुझे यहां दिखाए गए अनुसार मल्टीपार्ट / फॉर्म-डेटा अनुरोध का उपयोग करना चाहिए:
SO प्रश्न "C # क्लाइंट से मल्टीपार्ट फॉर्म"
मूल रूप से आप मैन्युअल रूप से एक अनुरोध लिखते हैं जो इस तरह एक प्रारूप का अनुसरण करता है:
Content-type: multipart/form-data, boundary=AaB03x
--AaB03x
content-disposition: form-data; name="field1"
Joe Blow
--AaB03x
content-disposition: form-data; name="pics"; filename="file1.txt"
Content-Type: text/plain
... contents of file1.txt ...
--AaB03x--
RFC 1867 से कॉपी किया गया - HTML में फ़ॉर्म-आधारित फ़ाइल अपलोड
यह फॉर्मेट किसी ऐसे व्यक्ति के लिए काफी परेशान करने वाला है जो JSON डेटा का अच्छा उपयोग करता है। तो जाहिर है कि समाधान JSON अनुरोध बनाने के लिए है और Base64 फ़ाइल को एन्कोड करें और इस तरह अनुरोध के साथ समाप्त करें:
{
"field1":"Joe Blow",
"fileImage":"JVBERi0xLjUKJe..."
}
और हम JSON क्रमांकन और deserialization का उपयोग कहीं भी कर सकते हैं जो हम चाहते हैं। उसके ऊपर, इस डेटा को भेजने का कोड काफी सरल है। आप सिर्फ JSON क्रमांकन के लिए अपनी कक्षा बनाते हैं और फिर गुण सेट करते हैं। फ़ाइल स्ट्रिंग संपत्ति कुछ तुच्छ लाइनों में सेट की गई है:
using (FileStream fs = File.Open(file_path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] file_bytes = new byte[fs.Length];
fs.Read(file_bytes, 0, file_bytes.Length);
MyJsonObj.fileImage = Convert.ToBase64String(file_bytes);
}
प्रत्येक आइटम के लिए और अधिक मूर्खतापूर्ण सीमांकक और हेडर नहीं। अब शेष प्रश्न प्रदर्शन का है। तो मैंने वो प्रोफाईल कर दी। मेरे पास 50 सैंपल फाइलों का एक सेट है, जिसे मुझे 50KB से लेकर 1.5MB तक के तार के पार भेजने की आवश्यकता होगी। पहले मैंने फ़ाइल को बाइट सरणी में स्ट्रीम करने के लिए कुछ पंक्तियाँ लिखीं ताकि उस तर्क की तुलना की जा सके जो फ़ाइल में स्ट्रीम होती है और फिर इसे बेस 64 स्ट्रीम में परिवर्तित कर देती है। नीचे कोड के 2 भाग दिए गए हैं जिन्हें मैंने प्रोफाइल किया है:
डायरेक्ट स्ट्रीम टू प्रोफाइल मल्टीपार्ट / फॉर्म-डेटा
var timer = new Stopwatch();
timer.Start();
using (FileStream fs = File.Open(file_path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] test_data = new byte[fs.Length];
fs.Read(test_data, 0, test_data.Length);
}
timer.Stop();
long test = timer.ElapsedMilliseconds;
//Write time elapsed and file size to CSV file
JSON अनुरोध बनाने वाली प्रोफ़ाइल को स्ट्रीम और एनकोड करें
var timer = new Stopwatch();
timer.Start();
using (FileStream fs = File.Open(file_path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] file_bytes = new byte[fs.Length];
fs.Read(file_bytes, 0, file_bytes.Length);
ret_file = Convert.ToBase64String(file_bytes);
}
timer.Stop();
long test = timer.ElapsedMilliseconds;
//Write time elapsed, file size, and length of UTF8 encoded ret_file string to CSV file
नतीजे यह थे कि साधारण रीड हमेशा 0ms लेता था, लेकिन यह कि Base64 एन्कोडिंग 5ms तक ले गया। नीचे सबसे लंबा समय है:
File Size | Output Stream Size | Time
1352KB 1802KB 5ms
1031KB 1374KB 7ms
463KB 617KB 1ms
हालाँकि, उत्पादन में आप कभी भी आँख बंद करके पहले अपने सीमांकक की जाँच किए बिना मल्टीपार्ट / फॉर्म-डेटा कभी नहीं लिखेंगे? इसलिए मैंने फॉर्म-डेटा कोड को संशोधित किया ताकि यह फ़ाइल में सीमांकक बाइट्स के लिए जाँच कर सके कि यह सुनिश्चित करने के लिए कि सबकुछ ठीक होगा। मैंने एक अनुकूलित स्कैनिंग एल्गोरिथ्म नहीं लिखा था, इसलिए मैंने केवल सीमांकक को छोटा बना दिया ताकि यह बहुत समय बर्बाद न करे।
var timer = new Stopwatch();
timer.Start();
using (FileStream fs = File.Open(file_path, FileMode.Open, FileAccess.Read, FileShare.Read))
{
byte[] test_data = new byte[fs.Length];
fs.Read(test_data, 0, test_data.Length);
string delim = "--DXX";
byte[] delim_checker = Encoding.UTF8.GetBytes(delim);
for (int i = 0; i <= test_data.Length - delim_checker.Length; i++)
{
bool match = true;
for (int j = i; j < i + delim_checker.Length; j++)
{
if (test_data[j] != delim_checker[j - i])
{
match = false;
break;
}
}
if (match)
{
break;
}
}
}
timer.Stop();
long test = timer.ElapsedMilliseconds;
अब परिणाम मुझे दिखा रहे हैं कि फॉर्म-डेटा विधि वास्तव में काफी धीमी होगी। नीचे समय के साथ परिणाम हैं> किसी भी विधि के लिए 0ms:
File Size | FormData Time | Json/Base64 Time
181Kb 1ms 0ms
1352Kb 13ms 4ms
463Kb 4ms 5ms
133Kb 1ms 0ms
133Kb 1ms 0ms
129Kb 1ms 0ms
284Kb 2ms 1ms
1031Kb 9ms 3ms
ऐसा लगता नहीं है कि एक अनुकूलित एल्गोरिथ्म बहुत बेहतर होगा या तो देखने के रूप में मेरा सीमांकक केवल 5 वर्ण लंबा था। 3x बेहतर नहीं वैसे भी, जो एक सीमांकक के लिए फ़ाइल बाइट्स की जाँच करने के बजाय बेस 64 एन्कोडिंग करने का प्रदर्शन लाभ है।
स्पष्ट रूप से बेस 64 एन्कोडिंग आकार को बढ़ाएगा जैसा कि मैं पहली तालिका में दिखाता हूं, लेकिन इसका वास्तव में यूनिकोड सक्षम यूटीएफ -8 के साथ भी बुरा नहीं है और यदि वांछित है तो अच्छी तरह से संपीड़ित करेगा। लेकिन वास्तविक लाभ यह है कि मेरा कोड अच्छा और साफ है और आसानी से समझ में आता है और यह JSON अनुरोध पेलोड को देखने के लिए मेरी आंखों को चोट नहीं पहुंचाता है।
तो क्यों पृथ्वी पर कोई भी बस आधारभूत रूप में मल्टीपार्ट / फॉर्म-डेटा का उपयोग करने की बजाय बेस 64 एनकोड फाइल को JSON में नहीं करता है? मानक हैं, लेकिन ये अक्सर अपेक्षाकृत बदलते हैं। मानक वास्तव में सिर्फ सुझाव हैं वैसे भी?