2012-10-03 15 views
46

मुझे वेबसॉकेट कम्यूनिकेशन मिला, मुझे बेस 64 एन्कोडेड स्ट्रिंग प्राप्त हुई, इसे यूंट 8 में परिवर्तित करें और उस पर काम करें, लेकिन अब मुझे वापस भेजने की जरूरत है, मुझे uint8 सरणी मिली है, और इसे बेस 64 स्ट्रिंग में बदलने की जरूरत है, इसलिए मैं भेज सकता हूं यह। मैं इस कनवर्टन को कैसे बना सकता हूं?uint8 ऐरे को base64 एन्कोडेड स्ट्रिंग में कैसे परिवर्तित करें?

+0

[Uint8array/ArrayBuffer <-> बेस 64 के लिए MDN कार्यान्वयन।] (Https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding#Solution_.232_.E2.80.93_rewriting_atob%28%29_and_btoa% 28% 29_using_TypedArrays_and_UTF-8) – JLRishe

उत्तर

106

आपके ब्राउज़र TextDecoder तो का उपयोग किया है कि यदि:

var u8 = new Uint8Array([65, 66, 67, 68]); 
var decoder = new TextDecoder('utf8'); 
var b64encoded = btoa(decoder.decode(u8)); 

आप browsers that do not have TextDecoder समर्थन करने के लिए की जरूरत है (वर्तमान में केवल आईई और एज), तो सबसे अच्छा विकल्प TextDecoder polyfill का उपयोग करना है।

अपने तार सादे ASCII और है नहीं multibyte यूनिकोड/UTF-8 तब देखते हैं String.fromCharCode का उपयोग कर एक सरल विकल्प है कि काफी सार्वभौमिक समर्थन किया जाना चाहिए है:

var u8 = new Uint8Array([65, 66, 67, 68]); 
var b64encoded = btoa(String.fromCharCode.apply(null, u8)); 

और Base64 स्ट्रिंग वापस डिकोड करने के लिए

var u8_2 = new Uint8Array(atob(b64encoded).split("").map(function(c) { 
    return c.charCodeAt(0); })); 

आप तो बहुत बड़े सरणी बफ़र्स है विफल हो सकता है लागू करते हैं और आप हिस्सा करने के लिए बफर (एक @RohitSengar द्वारा पोस्ट की के आधार पर) की आवश्यकता हो सकती हैं: एक Uint8Array करने के लिए। फिर, ध्यान दें कि यह केवल सही है अगर अपने बफर केवल गैर multibyte ASCII वर्ण हैं:

function Uint8ToString(u8a){ 
    var CHUNK_SZ = 0x8000; 
    var c = []; 
    for (var i=0; i < u8a.length; i+=CHUNK_SZ) { 
    c.push(String.fromCharCode.apply(null, u8a.subarray(i, i+CHUNK_SZ))); 
    } 
    return c.join(""); 
} 
// Usage 
var u8 = new Uint8Array([65, 66, 67, 68]); 
var b64encoded = btoa(Uint8ToString(u8)); 
+4

यह स्वीकार्य उत्तर होना चाहिए। – jutky

+0

बिल्कुल सही, यह वास्तव में काम करता है। –

+3

यह फ़ायरफ़ॉक्स में मेरे लिए काम कर रहा है, लेकिन क्रोम "अनकॉल्ड रेंज एरर: अधिकतम कॉल स्टैक आकार से अधिक हो गया है" (चोटी कर रहा है) के साथ चोक करता है। –

-3

यदि आप चाहते हैं कि बेस 64-एन्कोडर का जेएस कार्यान्वयन है, ताकि आप डेटा वापस भेज सकें, तो आप btoa फ़ंक्शन को आजमा सकते हैं।

b64enc = btoa(uint); 

btoa पर त्वरित कुछ नोट - यह गैर मानक है, तो ब्राउज़र इसका समर्थन करने के लिए मजबूर नहीं कर रहे हैं। हालांकि, अधिकांश ब्राउज़र करते हैं। कम से कम बड़े लोग। atob विपरीत रूपांतरण है।

यदि आपको एक अलग कार्यान्वयन की आवश्यकता है, या आपको एक एज-केस मिल गया है जहां ब्राउज़र को पता नहीं है कि आप किस बारे में बात कर रहे हैं, जेएस के लिए बेस 64 एन्कोडर खोजना बहुत कठिन नहीं होगा।

मुझे लगता है कि उनमें से 3 मेरी कंपनी की वेबसाइट पर चारों ओर फांसी, किसी कारण से देखते हैं ...

+0

धन्यवाद, मैंने पहले इसे आजमाया नहीं था। –

+10

नोट्स का जोड़ा। बीटा और एटोब वास्तव में एचटीएमएल 5 मानकीकरण प्रक्रिया का हिस्सा हैं और अधिकतर ब्राउज़र पहले से ही उसी तरह से उनका समर्थन करते हैं। दूसरा, btoa और atob केवल स्ट्रिंग के साथ काम करते हैं। Uint8Array पर चलने वाला बीओए पहले बफर को स्ट्रिंग() का उपयोग करके एक स्ट्रिंग में परिवर्तित करेगा। यह स्ट्रिंग "[ऑब्जेक्ट Uint8Array]" में परिणाम देता है। शायद यह नहीं है कि क्या इरादा है। – kanaka

+1

@CaioKeto आप अपने चुने हुए उत्तर को बदलने पर विचार करना चाहेंगे। यह जवाब सही नहीं है। – kanaka

13
function Uint8ToBase64(u8Arr){ 
    var CHUNK_SIZE = 0x8000; //arbitrary number 
    var index = 0; 
    var length = u8Arr.length; 
    var result = ''; 
    var slice; 
    while (index < length) { 
    slice = u8Arr.subarray(index, Math.min(index + CHUNK_SIZE, length)); 
    result += String.fromCharCode.apply(null, slice); 
    index += CHUNK_SIZE; 
    } 
    return btoa(result); 
} 

यदि आपके पास बहुत बड़ा Uint8Array है तो आप इस फ़ंक्शन का उपयोग कर सकते हैं। यह जावास्क्रिप्ट के लिए है, FileReader readAsArrayBuffer के मामले में उपयोगी हो सकता है।

+2

दिलचस्प बात यह है कि क्रोम में मैंने 300kb + बफर पर इसका समय लगाया और इसे आपके जैसे हिस्सों में ऐसा करने के लिए बाइट द्वारा बाइट करने से पहले थोड़ा धीमा होना है। यह मुझे आश्चर्यचकित कर दिया। – Matt

+0

@Matt दिलचस्प। यह संभव है कि इस दौरान, क्रोम अब इस रूपांतरण का पता लगाता है और इसके लिए एक विशिष्ट अनुकूलन है और डेटा को तोड़ने से इसकी दक्षता कम हो सकती है। – kanaka

+2

यह सुरक्षित नहीं है, है ना? यदि मेरी चंक की सीमा बहु-बाइट यूटीएफ 8 एन्कोडेड कैरेक्टर के माध्यम से कट जाती है, तो [सेरकोड()] (https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode) नहीं होगी सीमा के दोनों किनारों पर बाइट्स से समझदार पात्र बनाने में सक्षम, क्या यह होगा? – Jens

7

जावास्क्रिप्ट के लिए बहुत आसान समाधान और परीक्षण!

ToBase64 = function (u8) { 
    return btoa(String.fromCharCode.apply(null, u8)); 
} 

FromBase64 = function (str) { 
    return atob(str).split('').map(function (c) { return c.charCodeAt(0); }); 
} 

var u8 = new Uint8Array(256); 
for (var i = 0; i < 256; i++) 
    u8[i] = i; 

var b64 = ToBase64(u8); 
console.debug(b64); 
console.debug(FromBase64(b64)); 
+0

स्वच्छतम समाधान! – Abdel

0

मैं एक और समाधान जोड़ूंगा जो गैर-प्रिंट करने योग्य श्रेणियों के साथ काम करता है। मेरा अनुमान है कि यह TextEncoder और btoa चेनिंग से तेज़ है।

var blob = new Blob([ uint8ArrayBuffer ], { type: "image/jpeg" }); 
var imageUrl = URL.createObjectURL(blob); 

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

संबंधित मुद्दे