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


203

मुझे ArrayBufferएक बेस64 स्ट्रिंग में परिवर्तित करने के लिए एक कुशल (मूल पढ़ें) तरीके की आवश्यकता है जिसे मल्टीपार्ट पोस्ट पर उपयोग करने की आवश्यकता है।

जवाबों:


222
function _arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}

लेकिन, गैर देशी कार्यान्वयन हैं तेजी से जैसे https://gist.github.com/958841 देख http://jsperf.com/encoding-xhr-image-data/6


10
मैंने लिंक से गैर-देशी कार्यान्वयन की कोशिश की और 1M आकार के बफर को बदलने में 1min और आधा लिया, जबकि ऊपर का लूप कोड केवल 1sec लिया।
cshu

1
मुझे इस दृष्टिकोण की सादगी पसंद है, लेकिन यह सब स्ट्रिंग कॉन्सेप्टन महंगा हो सकता है। ऐसा लगता है कि पात्रों के एक सरणी का निर्माण और join()अंत में उन्हें फ़ायरफ़ॉक्स, IE, और सफारी पर काफी तेज है (लेकिन क्रोम पर काफी धीमा): jsperf.com/tobase64-implementations
JLRishe

मैं इस फ़ंक्शन का उपयोग सरणी बफ़र के लिए बेस 64 रूपांतरण में कर रहा हूं लेकिन मैं एरे बफर को वापस लाने में सक्षम नहीं हूं। मेरे पास एक _base64ToArrayBuffer () फंक्शन है: यहां कोडशेयरFailed to execute 'atob' on 'Window': The string to be decoded is not correctly encoded.
io

यह इस JSZip काम नहीं किया है। मैं एक और रास्ता खोजने github.com/michael/github/issues/137
RouR

1
मैं angualrjs और webapi2 का उपयोग करके 50mb पीडीएफ फाइल अपलोड की कोशिश कर रहा हूं। मैं उपर्युक्त लाइन कोड का उपयोग कर रहा हूं, अपलोड फ़ाइल के बाद, पृष्ठ दुर्घटनाग्रस्त हो गया और लटका दिया गया। कोड की लाइन के नीचे, मैं इस्तेमाल किया गया था, लेकिन वेबपी विधि में शून्य मान प्राप्त कर रहा था। "var base64String = btoa (String.fromCharCode.apply (null, new Uint8Array (arrayBuffer)));" कृपया कोई सुझाव दें ...
प्रभाकरन S

103

यह मेरे लिए ठीक काम करता है:

var base64String = btoa(String.fromCharCode.apply(null, new Uint8Array(arrayBuffer)));

ES6 में, वाक्य-विन्यास थोड़ा सरल है:

let base64String = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer)));

जैसा कि टिप्पणियों में बताया गया है, यह विधि ArrayBufferबड़े होने पर कुछ ब्राउज़रों में एक रनटाइम त्रुटि हो सकती है। सटीक आकार सीमा किसी भी मामले में कार्यान्वयन पर निर्भर है।


38
मुझे यह तरीका कंसीव करने के लिए बेहतर लगता है, लेकिन "अधिकतम कॉल स्टैक साइज से अधिक त्रुटि" प्राप्त करें। उपरोक्त लूप तकनीक उसी के आसपास मिलती है।
जय

13
मुझे एक स्टैक आकार की त्रुटि भी मिल रही है, इसलिए मैंने mobz के उत्तर का उपयोग किया और इसने बहुत अच्छा काम किया।
डेविड जोन्स

12
यह बड़े बफ़र्स के लिए काम नहीं किया। इसे काम करने के लिए थोड़ा सा संशोधन:btoa([].reduce.call(new Uint8Array(bufferArray),function(p,c){return p+String.fromCharCode(c)},''))
लैगिंगफ्लेक्स

1
मैं angualrjs और webapi2 का उपयोग करके 50mb पीडीएफ फाइल अपलोड की कोशिश कर रहा हूं। मैं उपर्युक्त लाइन कोड का उपयोग कर रहा हूं, अपलोड फ़ाइल के बाद, पृष्ठ दुर्घटनाग्रस्त हो गया और लटका दिया गया। कोड की लाइन के नीचे, मैं इस्तेमाल किया गया था, लेकिन वेबपी विधि में शून्य मान प्राप्त कर रहा था। "var base64String = btoa (String.fromCharCode.apply (null, new Uint8Array (arrayBuffer)));" कृपया कोई सुझाव दें ...
प्रभाकरण S

2
@Kugel btoaकोड रेंज 0-255 में वर्णों के लिए सुरक्षित है, क्योंकि यह यहां मामला है (8 के बारे में सोचो Uint8Array)।
गोटो 0

42

उन लोगों के लिए जो इसे कम पसंद करते हैं, यहां एक दूसरे का उपयोग करना है Array.reduceजो स्टैक ओवरफ्लो का कारण नहीं होगा:

var base64 = btoa(
  new Uint8Array(arrayBuffer)
    .reduce((data, byte) => data + String.fromCharCode(byte), '')
);

4
यकीन नहीं होता कि वाकई सेक्सी है। आखिरकार, आप <amount of Bytes in the buffer>नए तार पैदा कर रहे हैं।
नियोनित

कैसे के बारे में btoa(new Uint8Array(arraybuffer).reduce((data,byte)=>(data.push(String.fromCharCode(byte)),data),[]).join(''))?
रॉय टिंकर

35

एक और अतुल्यकालिक तरीका है Blob और FileReader का उपयोग करें।

मैंने प्रदर्शन का परीक्षण नहीं किया। लेकिन यह सोचने का एक अलग तरीका है।

function arrayBufferToBase64( buffer, callback ) {
    var blob = new Blob([buffer],{type:'application/octet-binary'});
    var reader = new FileReader();
    reader.onload = function(evt){
        var dataurl = evt.target.result;
        callback(dataurl.substr(dataurl.indexOf(',')+1));
    };
    reader.readAsDataURL(blob);
}

//example:
var buf = new Uint8Array([11,22,33]);
arrayBufferToBase64(buf, console.log.bind(console)); //"CxYh"

के dataurl.split(',', 2)[1]बजाय का उपयोग करें dataurl.substr(dataurl.indexOf(',')+1)
कार्टर मेडलिन

यह काम करने की गारंटी नहीं लगती है। W3c.github.io/FileAPI/#issue-f80bda5b के अनुसार readAsDataURLसैद्धांतिक रूप से एक प्रतिशत एन्कोडेड डेटारी वापस कर सकता है (और ऐसा लगता है कि यह वास्तव में jsdom में मामला है )
TS

@CarterMedlin splitसे बेहतर क्यों होगा substring?
TS

विभाजन छोटा है। लेकिन dataurl में एक या अधिक अल्पविराम (,) हो सकते हैं, विभाजन सुरक्षित नहीं है।
cuixiping

12

मैंने इसका इस्तेमाल किया और मेरे लिए काम करता है।

function arrayBufferToBase64( buffer ) {
    var binary = '';
    var bytes = new Uint8Array( buffer );
    var len = bytes.byteLength;
    for (var i = 0; i < len; i++) {
        binary += String.fromCharCode( bytes[ i ] );
    }
    return window.btoa( binary );
}



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;
}

असुरक्षित। @Chemoish उत्तर देखें
कुगेल

11

इसके लिए मेरी सिफारिश देशी btoaरणनीतियों का उपयोग नहीं करने की है - क्योंकि वे सही ढंग से सभी को सांकेतिक शब्दों में बदलना नहीं है ArrayBuffer...

DOMs atob () और btoa () को फिर से लिखें

चूंकि DOMStrings 16-बिट-एन्कोडेड स्ट्रिंग्स हैं, इसलिए ज्यादातर यूनिकोड स्ट्रिंग पर window.btoa कॉल करने वाले ब्राउज़र में कैरेक्टर आउट ऑफ रेंज अपवाद होगा यदि कोई कैरेक्टर 8-बिट ASCII-एन्कोडेड कैरेक्टर की सीमा से अधिक है।

जबकि मुझे इस सटीक त्रुटि का कभी सामना नहीं करना पड़ा है, मैंने पाया है कि ArrayBufferमैंने जिन लोगों को एनकोड करने की कोशिश की है उनमें से कई ने गलत तरीके से एनकोड किया है।

मैं या तो एमडीएन सिफारिश या जिस्ट का उपयोग करूंगा।


btoaस्ट्रिंग पर काम नहीं करता है, लेकिन ओपी पूछ रहा है ArrayBuffer
tsh

1
बहुत ज्यादा, यहाँ इतने सारे स्निपेट्स जो गलत चीज़ की सलाह देते हैं! मैंने इस त्रुटि को कई बार देखा है, जहाँ लोग आँख बंद करके और बोटो का उपयोग करते हैं।
कुगेल

4
सभी सरणी बफ़र्स को अन्य उत्तरों में रणनीतियों का उपयोग करके ठीक से एन्कोड किया जाना चाहिए, एटोब / बोटो केवल पाठ के लिए एक समस्या है जिसमें 0xFF से अधिक वर्ण होते हैं (जो परिभाषा द्वारा बाइट सरणियों को नहीं करते हैं)। MDN चेतावनी लागू नहीं होती है क्योंकि अन्य उत्तरों में रणनीति का उपयोग करते समय आपको एक स्ट्रिंग की गारंटी दी जाती है जिसमें केवल ASCII वर्ण होते हैं क्योंकि Uint8Array से किसी भी मान को 0 और 255 के बीच होने की गारंटी है जिसका अर्थ है String.frombharCode गारंटी है एक ऐसे चरित्र को वापस करने के लिए जो सीमा से बाहर नहीं है।
जेम्सनरेटर

11
var blob = new Blob([arrayBuffer])

var reader = new FileReader();
reader.onload = function(event){
   var base64 =   event.target.result
};

reader.readAsDataURL(blob);

1
कृपया अपने उत्तर में कुछ स्पष्टीकरण जोड़ें। इस कोड का क्या अर्थ है?
ऑस्कर


1
यह अब तक का सबसे तेज़ दृष्टिकोण है - मेरे सीमित परीक्षण में अन्य लोगों की तुलना में दस गुना तेज
जितिन

काश मुझे यह समाधान 8 घंटे फिर से मिल जाता। मेरा दिन बर्बाद नहीं होता; (साभार
कैसर शाहिद

7

नीचे U648Array को Base64 स्ट्रिंग में बदलने और फिर से वापस करने के लिए 2 सरल कार्य दिए गए हैं

arrayToBase64String(a) {
    return btoa(String.fromCharCode(...a));
}

base64StringToArray(s) {
    let asciiString = atob(s);
    return new Uint8Array([...asciiString].map(char => char.charCodeAt(0)));
}

1
यह एक भ्रमित करने वाला उत्तर है। यह मान्य जावास्क्रिप्ट की तरह नहीं दिखता है और Uint8Array एक ArrayBuffer है?
user1153660

@ user1153660 functionकीवर्ड जोड़ें और इसे एक आधुनिक ब्राउज़र में काम करना चाहिए।
यति

बहुत बढ़िया! btoa (String.fromCharCode (... एक)); सबसे छोटा संस्करण है जिसे मैंने अब तक Uint8Array को एनकोड करने के लिए देखा है।
निकोलो

1
यह अच्छा लग रहा है लेकिन अगर सरणी बहुत बड़ा है तो यह अधिकतम कॉल स्टैक आकार को त्रुटि से अधिक फेंक देगा।
पवेल Psztyć

0

आप ArrayBufferका उपयोग करके एक सामान्य सरणी प्राप्त कर सकते हैं Array.prototype.slice। एक फ़ंक्शन का उपयोग करें जैसे Array.prototype.mapकि बाइट्स को वर्णों में बदलना और joinउन्हें एक साथ फ़ॉर्म स्ट्रिंग करना।

function arrayBufferToBase64(ab){

    var dView = new Uint8Array(ab);   //Get a byte view        

    var arr = Array.prototype.slice.call(dView); //Create a normal array        

    var arr1 = arr.map(function(item){        
      return String.fromCharCode(item);    //Convert
    });

    return window.btoa(arr1.join(''));   //Form a string

}

यह विधि तेज़ है क्योंकि इसमें कोई स्ट्रिंग कॉन्फेंशन नहीं चल रहे हैं।


असुरक्षित। @Chemoish उत्तर देखें
Kugel

0

ओपी ने रनिंग एनवायरमेंट को निर्दिष्ट नहीं किया, लेकिन यदि आप नोड का उपयोग कर रहे हैं। तो ऐसा काम करने के लिए एक बहुत ही सरल तरीका है।

आधिकारिक Node.JS डॉक्स https://nodejs.org/api/buffer.html#buffer_buffers_and_character_encodings के साथ समझौते

// This step is only necessary if you don't already have a Buffer Object
const buffer = Buffer.from(yourArrayBuffer);

const base64String = buffer.toString('base64');

इसके अलावा, यदि आप उदाहरण के लिए कोणीय के तहत चल रहे हैं, तो बफ़र क्लास भी एक ब्राउज़र वातावरण में उपलब्ध कराया जाएगा।


आपका उत्तर केवल NodeJS पर लागू होता है और ब्राउज़र में काम नहीं करेगा।
jvatic

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

-3

मेरी ओर से, क्रोम नेविगेटर का उपयोग करके, मुझे एक सरणी बफ़र पढ़ने के लिए डेटा व्यू () का उपयोग करना था

function _arrayBufferToBase64( tabU8A ) {
var binary = '';
let lecteur_de_donnees = new DataView(tabU8A);
var len = lecteur_de_donnees.byteLength;
var chaine = '';
var pos1;
for (var i = 0; i < len; i++) {
    binary += String.fromCharCode( lecteur_de_donnees.getUint8( i ) );
}
chaine = window.btoa( binary )
return chaine;}

-4
function _arrayBufferToBase64(uarr) {
    var strings = [], chunksize = 0xffff;
    var len = uarr.length;

    for (var i = 0; i * chunksize < len; i++){
        strings.push(String.fromCharCode.apply(null, uarr.subarray(i * chunksize, (i + 1) * chunksize)));
    }

    return strings.join("");
}

यह बेहतर है, अगर आप स्ट्रिंग से अनपैक आर्काइव के लिए JSZip का उपयोग करते हैं

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