Base64 स्ट्रिंग को ArrayBuffer में बदलें


96

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

मुझे वे लिंक दिलचस्प लगे, लेकिन उन्होंने मेरी मदद नहीं की:

Ar64Buffer से base64 एन्कोडेड स्ट्रिंग

यह विपरीत रूपांतरण के बारे में है, ArrayBuffer से base64 तक, दूसरे तरीके से नहीं

http://jsperf.com/json-vs-base64/2

यह अच्छा लग रहा है, लेकिन मैं यह पता नहीं लगा सकता कि कोड का उपयोग कैसे करें।

क्या रूपांतरण करने का एक आसान (शायद देशी) तरीका है? धन्यवाद

जवाबों:


144

इसे इस्तेमाल करे:

function _base64ToArrayBuffer(base64) {
    var binary_string = window.atob(base64);
    var len = binary_string.length;
    var bytes = new Uint8Array(len);
    for (var i = 0; i < len; i++) {
        bytes[i] = binary_string.charCodeAt(i);
    }
    return bytes.buffer;
}

3
कृपया मुझे समझाएं कि यहां वास्तव में क्या हो रहा है।
गोविंदा सखारे

4
वैसे यह बहुत सीधा है, पहले हम बेस 64 स्ट्रिंग (एटोब) को डिकोड करते हैं, फिर हम डिकोड किए गए स्ट्रिंग के समान लंबाई के साथ 8-बिट अहस्ताक्षरित पूर्णांक के नए सरणी बनाते हैं। उसके बाद हम स्ट्रिंग को पुनरावृत्त करते हैं और स्ट्रिंग में प्रत्येक वर्ण के यूनिकोड मान के साथ सरणी को पॉप्युलेट करते हैं।
गोरान।

2
MDN से: Base64 इसी तरह के बाइनरी-टू-टेक्स्ट एन्कोडिंग योजनाओं का एक समूह है जो एक ASCII स्ट्रिंग प्रारूप में बाइनरी डेटा को रेडिक्स -64 प्रतिनिधित्व में अनुवाद करके प्रस्तुत करता है। Uint8Array टाइप की गई सरणी 8-बिट अहस्ताक्षरित पूर्णांक की एक सरणी का प्रतिनिधित्व करती है, और हम डेटा के ASCII प्रतिनिधित्व के साथ काम कर रहे हैं (जो कि 8-बिट तालिका भी है) ..
गोरान.इट

3
यह सही नहीं है। यह जावास्क्रिप्ट को स्ट्रिंग के रूप में बाइट्स की व्याख्या करने की अनुमति देता है, जो डेटा को प्रभावित करता है जो वास्तव में सच बाइनरी है।
टॉम ज़ातो -

4
समस्या यह है कि ए) हर बाइट अनुक्रम वैध यूनिकोड नहीं है बी) यूनिकोड में प्रत्येक चरित्र एक बाइट नहीं है, इसलिए bytes[i] = binary_string.charCodeAt(i);गलत हो सकता है
मिश्रण

51

TypedArray.from का उपयोग करना :

Uint8Array.from(atob(base64_string), c => c.charCodeAt(0))

प्रदर्शन की तुलना गोरान के लूप संस्करण के साथ की जाती है। यह उत्तर है।


2
इस तरह के एक लाइनर को कौन पसंद करता है, यह ध्यान रखें कि Uint8Array.fromअभी भी कुछ ब्राउज़रों के साथ कम संगतता है।
इज़ुमसी

2
कृपया atob या btoa की सिफारिश न करें: developer.mozilla.org/en-US/docs/Web/API/WindowBase64/…
Kugel

रेल संकलक इस स्ट्रिंग को संभाल नहीं सकता है और इसके साथ विफल रहता है ExecJS::RuntimeError: SyntaxError: Unexpected token: operator (>); (रेल 5)
एवल क्रोस

3
यह एक सरणी बफ़र नहीं है। यह टाइप किया गया ऐरे है। आपको उस .bufferसंपत्ति के माध्यम से सरणी बफ़र तक पहुंच मिलती है , जो से लौटी हैUint8Array
oligofren

4
@ साइट, इसमें कुछ भी गलत नहीं है atobया btoa, आपको बस इन्हें वैध इनपुट देना होगा। atobएक वैध आधार 64 स्ट्रिंग की आवश्यकता है, अन्यथा यह एक त्रुटि फेंक देगा। और btoaएक वैध बाइट स्ट्रिंग (जिसे बाइनरी स्ट्रिंग भी कहा जाता है) की आवश्यकता होती है जो कि 0-255 की सीमा में एक स्ट्रिंग युक्त वर्ण होता है। यदि आपके स्ट्रिंग में उस सीमा के बाहर वर्ण हैं, btoaतो एक त्रुटि होगी।
GetFree

33

जावास्क्रिप्ट में यूनिकोड समस्या के कारण Goran.it का जवाब काम नहीं करता है - https://developer.mozilla.org/en-US/docs/Web/API/WindowBase64/Base64_encoding-and_decoding

मैंने डैनियल गुरेरो के ब्लॉग पर दिए गए फ़ंक्शन का उपयोग करके समाप्त किया: http://blog.danguer.com/2011/10/24/base64-binary-decoding-in-javascript/

फ़ंक्शन को जीथब लिंक पर सूचीबद्ध किया गया है: https://github.com/danguer/blog-examples/blob/master/js/base64-binary.js

इन पंक्तियों का उपयोग करें

var uintArray = Base64Binary.decode(base64_string);  
var byteArray = Base64Binary.decodeArrayBuffer(base64_string); 

1
यह विधि एटब का उपयोग करने की तुलना में 2x तेज है।
xiaoyu2er

4
क्या आप एक उदाहरण दे सकते हैं जिसके लिए यह काम नहीं करेगा? लेख मनमाने ढंग से तारों को कूटने के बारे में बात करता है, जिसमें यूनिकोड वर्ण हो सकते हैं, लेकिन यह बिल्कुल भी लागू नहीं होता है atob
riv

1
decodeArrayBufferरिटर्न जिसका ArrayBufferआकार हमेशा 3 से विभाज्य होता है, जो मुझे समझ में नहीं आता है कि क्या यह डिज़ाइन या बग द्वारा है। मैं गितुब परियोजना में पूछूंगा।
सेप्टिको

@ceztko यह शायद (आकस्मिक) डिजाइन द्वारा है। Base64 एन्कोडिंग एल्गोरिथ्म 3 बाइट्स के समूह लेता है और उन्हें 4 वर्णों में बदल देता है। डिकोड विधि संभवत: एक ArrayBuffer आवंटित करती है जिसकी लंबाई base64String.length / 4 * 3 बाइट्स होती है और समाप्त होने पर किसी भी अप्रयुक्त बाइट्स को कभी नहीं काटता है।
हमेशा

1
@AlwaysLearning जिसका अर्थ है कि यह संभवतः बगुला है क्योंकि बचे हुए शून्य बाइट्स का इरादा आउटपुट सामग्री को दूषित कर सकता है।
13

21

बस बेस 64-सरणीबफ़र मिला, अविश्वसनीय रूप से उच्च उपयोग के साथ एक छोटा एनएमपी पैकेज, पिछले महीने (2017-08) में 5 एम डाउनलोड।

https://www.npmjs.com/package/base64-arraybuffer

किसी के लिए एक बेहतरीन मानक समाधान की तलाश में, यह हो सकता है।


9

Async समाधान, डेटा बड़ा होने पर बेहतर है:

// base64 to buffer
function base64ToBufferAsync(base64) {
  var dataUrl = "data:application/octet-binary;base64," + base64;

  fetch(dataUrl)
    .then(res => res.arrayBuffer())
    .then(buffer => {
      console.log("base64 to buffer: " + new Uint8Array(buffer));
    })
}

// buffer to base64
function bufferToBase64Async( buffer ) {
    var blob = new Blob([buffer], {type:'application/octet-binary'});    
    console.log("buffer to blob:" + blob)

    var fileReader = new FileReader();
    fileReader.onload = function() {
      var dataUrl = fileReader.result;
      console.log("blob to dataUrl: " + dataUrl);

      var base64 = dataUrl.substr(dataUrl.indexOf(',')+1)      
      console.log("dataUrl to base64: " + base64);
    };
    fileReader.readAsDataURL(blob);
}

6

जावास्क्रिप्ट एक अच्छा विकास वातावरण है, इसलिए यह अजीब लगता है कि यह इस छोटी सी समस्या का समाधान प्रदान नहीं करता है। इस पृष्ठ पर कहीं और दिए गए समाधान संभावित रूप से धीमे हैं। यहाँ मेरा समाधान है। यह इनबिल्ट फंक्शनलिटी को रोजगार देता है जो बेस 64 इमेज और साउंड डेटा यूरल्स को डिकोड करता है।

var req = new XMLHttpRequest;
req.open('GET', "data:application/octet;base64," + base64Data);
req.responseType = 'arraybuffer';
req.onload = function fileLoaded(e)
{
   var byteArray = new Int8Array(e.target.response);
   // var shortArray = new Int16Array(e.target.response);
   // var unsignedShortArray = new Int16Array(e.target.response);
   // etc.
}
req.send();

यदि आधार 65 स्ट्रिंग बुरी तरह से बनता है तो भेजने का अनुरोध विफल हो जाता है।

माइम प्रकार (एप्लिकेशन / ऑक्टेट) संभवतः अनावश्यक है।

क्रोम में परीक्षण किया गया। अन्य ब्राउज़रों में काम करना चाहिए।


1
यह मेरे लिए, सरल और साफ समाधान था। मैंने जल्दी से फ़ायरफ़ॉक्स, IE 11, एज में इसका परीक्षण किया और ठीक काम किया!
cs-NET

मूल प्रश्न से संबंधित नहीं है
जेम्स न्यूटन

मुझे यकीन नहीं है कि यह IE11 में आपके लिए कैसे काम करता है, लेकिन मुझे एक Access Deniedत्रुटि मिलती है , जो एक कॉर्स सीमा लगती है।
सर्गीउ

6

Node.js उपयोगकर्ताओं के लिए:

const myBuffer = Buffer.from(someBase64String, 'base64');

myBuffer प्रकार बफर का होगा जो Uint8Array का एक उपवर्ग है। दुर्भाग्य से, Uint8Array एक ArrayBuffer नहीं है जैसा कि ओपी पूछ रहा था। लेकिन जब एक ArrayBuffer में हेरफेर करता है तो मैं लगभग हमेशा इसे Uint8Array या कुछ इसी तरह से लपेटता हूं, इसलिए इसे उसके लिए कहा जाना चाहिए।


2

शुद्ध जेएस - कोई स्ट्रिंग मिडलस्टेप (कोई एटब नहीं)

मैं निम्नलिखित फ़ंक्शन लिखता हूं जो बेस 64 को सीधे तरीके से परिवर्तित करते हैं (मिडलस्टेप में स्ट्रिंग में रूपांतरण के बिना)। विचार

  • 4 base64 वर्ण प्राप्त करें
  • Base64 वर्णमाला में प्रत्येक वर्ण का सूचकांक खोजें
  • सूचकांक को 6-बिट संख्या (बाइनरी स्ट्रिंग) में बदलें
  • चार 6 बिट संख्याओं को मिलाएं जो 24-बिट संख्या देता है (बाइनरी स्ट्रिंग के रूप में संग्रहीत)
  • 24-बिट स्ट्रिंग को तीन 8-बिट में विभाजित करें और प्रत्येक को संख्या में कवर करें और उन्हें आउटपुट सरणी में संग्रहीत करें
  • कोने का मामला: यदि इनपुट बेस 64 स्ट्रिंग एक / दो =चार के साथ समाप्त होती है , तो आउटपुट सरणी से एक / दो नंबर हटा दें

नीचे समाधान बड़े इनपुट बेस 64 स्ट्रिंग्स को संसाधित करने की अनुमति देता है। बाइट के बिना बाइट्स को बेस 64 में कन्वर्ट करने के लिए इसी तरह का कार्य यहां है


तो कोई याद नहीं ""?
गोलसॉफ्ट एबी

एक ब्राउज़र में परीक्षण करें, मुझे यकीन नहीं है कि यह अपेक्षित परिणाम है? "एलिस इन एडवेंचर इन वंडरलैंड " (अर्थात अंतिम चरित्र
ना है

1
@GillsoftAB इस जानकारी के लिए धन्यवाद - आप सही हैं - मैं इस समस्या को ठीक करता हूं
कामिल कीलवेज़्स्की

-3
const str = "dGhpcyBpcyBiYXNlNjQgc3RyaW5n"
const encoded = new TextEncoder().encode(str) // is Uint8Array
const buf = encoded.buffer // is ArrayBuffer

6
ध्यान दें कि यह कोई बेस 64 डिकोडिंग / एन्कोडिंग नहीं करता है। यह "बेस64" के 6 बाइट्स को 6-तत्व ArrayBuffer या Uint8Array में बदल देता है।
डबेक

2
@dubek यही पूछा गया है।
एंड्री नेमचेंको
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.