ترميز/فك ترميز Base64 في JavaScript: btoa() و atob() و Unicode
ترميز وفك ترميز Base64 في JavaScript
توفر JavaScript عدة طرق مضمنة لترميز وفك ترميز سلاسل Base64. سواء كنت تبني تطبيق متصفح أو خادم Node.js، فإن فهم كيفية العمل مع Base64 ضروري للتعامل مع البيانات الثنائية في الصيغ النصية مثل JSON و HTML وعناوين URL.
استخدام btoa() و atob() في المتصفح
الدالتان الأساسيتان لـ Base64 في JavaScript في المتصفح هما btoa() و atob(). تتبع هاتان الدالتان اصطلاح تسمية قديم — btoa تعني "binary to ASCII" (من ثنائي إلى ASCII) و atob تعني "ASCII to binary" (من ASCII إلى ثنائي). وقد تم دعمهما في جميع المتصفحات الرئيسية لعقود.
الترميز باستخدام btoa()
const originalString = 'Hello, world!';
const encoded = btoa(originalString);
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ==
فك الترميز باستخدام atob()
const base64String = 'SGVsbG8sIHdvcmxkIQ==';
const decoded = atob(base64String);
console.log(decoded);
// Output: Hello, world!
تعمل كلتا الدالتين مع السلاسل التي تحتوي فقط على أحرف Latin-1 (كل حرف يمثله بايت واحد). هذا قيد مهم سنتناوله لاحقًا.
التعامل مع Unicode والأحرف غير ASCII
مشكلة شائعة: ترمي btoa() خطأً عند إعطائها سلاسل تحتوي على أحرف خارج نطاق Latin-1، مثل الإيموجي أو الأحرف الصينية أو الأحرف المعلمة بعلامات.
btoa('Hello 你好');
// Error: The string to be encoded contains characters outside of the Latin-1 range.
لترميز سلاسل Unicode، تحتاج إلى تحويل السلسلة إلى بايتات أولاً ثم ترميز تلك البايتات. يستخدم الأسلوب الحديث واجهتي TextEncoder و TextDecoder:
function unicodeToBase64(str) {
const bytes = new TextEncoder().encode(str);
const binaryString = String.fromCharCode(...bytes);
return btoa(binaryString);
}
function base64ToUnicode(base64) {
const binaryString = atob(base64);
const bytes = Uint8Array.from(binaryString, (c) => c.charCodeAt(0));
return new TextDecoder().decode(bytes);
}
// Usage
const encoded = unicodeToBase64('Hello 你好 🚀');
console.log(encoded);
// Output: SGVsbG8g5L2g5aW9IPCfj4A=
const decoded = base64ToUnicode(encoded);
console.log(decoded);
// Output: Hello 你好 🚀
تستخدم تقنية أقدم encodeURIComponent و decodeURIComponent، لكن أسلوب TextEncoder/TextDecoder أكثر متانة وهو الحل الحديث الموصى به.
ترميز البيانات الثنائية (ArrayBuffer)
عند العمل مع الملفات أو الصور أو البيانات الثنائية الخام من واجهات برمجة التطبيقات مثل fetch أو FileReader، يكون لديك عادةً ArrayBuffer أو Uint8Array. إليك كيفية تحويلها إلى Base64:
function arrayBufferToBase64(buffer) {
const bytes = new Uint8Array(buffer);
let binaryString = '';
for (let i = 0; i < bytes.length; i++) {
binaryString += String.fromCharCode(bytes[i]);
}
return btoa(binaryString);
}
function base64ToArrayBuffer(base64) {
const binaryString = atob(base64);
const bytes = new Uint8Array(binaryString.length);
for (let i = 0; i < binaryString.length; i++) {
bytes[i] = binaryString.charCodeAt(i);
}
return bytes.buffer;
}
تحويل ملف إلى Base64 في المتصفح
إليك مثال كامل باستخدام FileReader لتحويل ملف يختاره المستخدم إلى عنوان URL بيانات Base64:
function fileToBase64(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.onerror = () => reject(new Error('Failed to read file'));
reader.readAsDataURL(file);
});
}
// Usage with a file input
document.querySelector('input[type="file"]').addEventListener('change', async (e) => {
const file = e.target.files[0];
try {
const dataUrl = await fileToBase64(file);
console.log(dataUrl); // data:image/png;base64,iVBORw0KGgo...
} catch (err) {
console.error('Conversion failed:', err);
}
});
استخدام Base64 في Node.js
توفر Node.js فئة Buffer لعمليات Base64، وهي أكثر مرونة من btoa/atob في المتصفح. تتعامل فئة Buffer مع الترميز وفك الترميز تلقائيًا، بما في ذلك Unicode، وتدعم صيغ ترميز متعددة.
الترميز وفك الترميز الأساسي
// Encode a string to Base64
const encoded = Buffer.from('Hello, world!').toString('base64');
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ==
// Decode a Base64 string back to text
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// Output: Hello, world!
دعم Unicode في Node.js
على عكس btoa() في المتصفح، يتعامل Buffer في Node.js مع Unicode بسلاسة:
const encoded = Buffer.from('Hello 你好 🚀').toString('base64');
console.log(encoded);
// Output: SGVsbG8g5L2g5aW9IPCfj4A=
const decoded = Buffer.from(encoded, 'base64').toString('utf-8');
console.log(decoded);
// Output: Hello 你好 🚀
قراءة ملف وترميزه كـ Base64
const fs = require('fs');
// Read a file and encode it to Base64
const buffer = fs.readFileSync('image.png');
const base64 = buffer.toString('base64');
const dataUrl = `data:image/png;base64,${base64}`;
ترميز Base64url في Node.js
يدعم Node.js 15.7.0+ ترميز Base64url الأصلي، الذي يستبدل + بـ - و / بـ _ ويحذف الحشو:
const encoded = Buffer.from('Hello, world!').toString('base64url');
console.log(encoded);
// Output: SGVsbG8sIHdvcmxkIQ (no padding)
const decoded = Buffer.from(encoded, 'base64url').toString('utf-8');
console.log(decoded);
// Output: Hello, world!
اعتبارات الأداء
بالنسبة للبيانات الكبيرة، يمكن أن تكون عمليات Base64 المتكررة بطيئة. إليك بعض النصائح:
- استخدم
TextEncoder/TextDecoderبدلاً من التحويلات اليدوية لسلاسل Unicode - في Node.js،
Buffer.from()محسّن بشكل كبير — فضّله على التطبيقات اليدوية - تجنب تحويل الملفات الكبيرة إلى Base64 إلا عند الضرورة (فكّر في التدفق streaming)
- بالنسبة لمجموعات البيانات الكبيرة، فكّر في استخدام
BlobوFileReaderفي المتصفح لتجنب حظر الخيط الرئيسي
جرّب ترميز Base64 عبر الإنترنت
جرّب الترميز وفك الترميز مباشرة في متصفحك باستخدام أداة ترميز وفك ترميز Base64 المجانية عبر الإنترنت. لا حاجة للبرمجة — فقط الصق النص أو ارفع ملفًا واحصل على نتيجة Base64 فورًا.