مستوى المقال: متوسط. محتاج تكون عارف يعني إيه بايت وبت، وكتبت كود بسيط بأي لغة قبل كده. مش لازم تكون خبير.
Base64: ليه الملف بيتحوّل لنص وبيكبر الثلث
لو بعتّ صورة جوه رسالة أو خزّنتها في حقل JSON ولقيتها بقت نص طويل زي iVBORw0KGgo... وحجمها زاد حوالي الثلث، ده مش خلل. ده ترميز Base64 بيشتغل بالظبط زي ما المفروض. المقال ده هيخليك تعرف امتى تستخدمه وامتى تبعد عنه، وليه بيكلّفك 33% زيادة في الحجم.
المشكلة باختصار
فيه قنوات نقل قديمة اتبنت علشان تنقل نص بس: الإيميل (SMTP)، وبعض ترويسات HTTP، وملفات إعدادات زي JSON وXML. القنوات دي بتتعامل مع بايتات معينة كأوامر تحكّم مش كبيانات. لو بعتّ بايت خام لصورة أو ملف مضغوط، فيه بايتات ممكن القناة تفسّرها غلط أو تقطعها. النتيجة: الملف بيوصل تالف. Base64 بيحل ده بإنه يحوّل أي بايتات لنص من 64 رمز آمن بس، بيعدّي من غير ما يتلخبط.
المفهوم بمثال بسيط الأول
تخيّل مكتب بريد قديم بيرفض يشحن أي طرد فيه حاجة غير الحروف والأرقام. عندك لوحة رخامية عايز تبعتها. مش هيعدّوها. الحل: بدل ما تبعت اللوحة نفسها، تكتب وصف دقيق ليها بالحروف بس: "مستطيل، 30 في 40، الحرف الأول محفور في الركن..."، والطرف التاني يعيد نحتها من الوصف. الوصف أطول من اللوحة الأصلية، بس بيعدّي من غير مشاكل.
Base64 بيعمل نفس الحاجة. البيانات الأصلية (بايتات) هي اللوحة. الوصف المكتوب بالحروف هو نص Base64. الطرف التاني بيفكّ الوصف ويرجّع البايتات زي ما هي بالظبط. مفيش فقدان، بس فيه زيادة في الطول.
المفهوم علميًا: 3 بايت بيبقوا 4 رموز
البايت الواحد 8 بت. Base64 بيشتغل على 6 بت في المرة، علشان 2 أُس 6 يساوي 64 رمز بالظبط، وده مصدر الاسم. الخوارزمية بتاخد كل 3 بايت (24 بت)، وتقسّمهم لأربع مجموعات، كل مجموعة 6 بت. كل مجموعة رقم من 0 لـ 63، وكل رقم بيتحوّل لرمز من الجدول: A–Z ثم a–z ثم 0–9 ثم + و /.
ركز في الحساب: دخل 3 بايت، خرج 4 رموز. كل رمز محتاج بايت لتخزينه كنص. يعني 3 بايت أصلية بقت 4 بايت. الزيادة 1 على 3، يعني 33% بالظبط. دي مش مصادفة ولا هدر عشوائي، دي طبيعة الترميز نفسه.
مثال تنفيذي شغّال
الكود ده يشفّر ويفك كلمة، وبعدين يقيس الزيادة في الحجم على ملف حقيقي:
import base64
# تشفير وفك بسيط
raw = "Man".encode("utf-8") # 3 بايت
encoded = base64.b64encode(raw) # b'TWFu' -- 4 رموز
decoded = base64.b64decode(encoded) # يرجّع b'Man' بالظبط
print(encoded.decode(), decoded.decode()) # TWFu Man
# قياس الزيادة على صورة حقيقية
with open("photo.jpg", "rb") as f:
data = f.read()
b64 = base64.b64encode(data)
overhead = (len(b64) - len(data)) / len(data) * 100
print(f"الأصلي: {len(data):,} بايت")
print(f"بعد Base64: {len(b64):,} بايت")
print(f"الزيادة: {overhead:.1f}%") # حوالي 33.3%
ولو عايز تجربة سريعة من الترمينال من غير ما تكتب سكربت:
# يشفّر ملف ويطبع أول سطر من الناتج
base64 photo.jpg | head -c 60; echo
# يقارن الحجمين بالبايت
echo "الأصلي: $(wc -c < photo.jpg)"
echo "المشفّر: $(base64 photo.jpg | wc -c)"
سيناريو واقعي: صورة جوه JSON
افترض عندك API بيرجّع بيانات مستخدم، وقررت تحطّ صورة البروفايل جواها مباشرة كـ Base64 بدل ما ترجّع رابط. الصورة أصلها 3 ميجابايت. بعد Base64 بتبقى حوالي 4 ميجابايت. لو عندك 10 آلاف طلب في الساعة، انت بتنقل 10 جيجابايت زيادة كل ساعة على الشبكة من غير أي فايدة. ده غير إن الـ JSON كله بيتحمّل في الذاكرة مرة واحدة عند التحليل، فبتضغط على الرام كمان. المكسب الوحيد إنك وفّرت طلب HTTP واحد. الثمن كبير جدًا مقابل مكسب صغير.
الـ trade-off بوضوح
Base64 بيكسبك حاجة واحدة مهمة: نقل بيانات ثنائية بأمان عبر قنوات نصية، وتضمين البيانات جوه النص نفسه (زي data URI في الـ CSS). بتخسر مقابلها: 33% زيادة في الحجم، وشوية معالجة CPU للتشفير والفك. القاعدة: استخدمه لما تكون مضطر تحطّ بيانات ثنائية جوه وسط نصّي، مش لما يكون عندك بديل بينقل البايتات على طبيعتها.
ملاحظة مهمة: Base64 مش تشفير أمان
ناس كتير بتفتكر إن Base64 بيأمّن البيانات. غلط. أي حد يقدر يفكّه في سطر واحد. هو ترميز (encoding) مش تعمية (encryption). لو عايز تحمي بيانات حساسة، استخدم TLS للنقل وخوارزمية تشفير حقيقية زي AES للتخزين. Base64 بيخفي شكل البيانات بس، مش محتواها.
متى لا تستخدم Base64
الطريقة دي بتفشل كاختيار افتراضي في الحالات دي:
- رفع ملفات كبيرة عبر HTTP: استخدم
multipart/form-dataاللي بينقل البايتات على طبيعتها من غير 33% زيادة. - تخزين صور في قاعدة البيانات: خزّن الملف على تخزين كائنات (S3 أو ما شابه) واحفظ الرابط بس. تخزين Base64 بيكبّر الصفوف ويبطّئ الاستعلامات.
- أي مسار حسّاس للأداء بينقل ميجابايتات: الزيادة بتتراكم بسرعة على السكيل.
الافتراض هنا إن عندك بديل بينقل ثنائي مباشر. لو القناة نصية بحتة ومفيش بديل (زي تضمين أيقونة صغيرة 2 كيلوبايت في CSS)، ساعتها Base64 هو الحل الصح.
الخطوة التالية
افتح أي API عندك بيرجّع صور أو ملفات مضمّنة كـ Base64. قيس حجم الاستجابة قبل وبعد ما تحوّلها لروابط. لو الفرق أكتر من ميجابايت في الطلب الواحد، حوّلها لروابط وسيب Base64 للأيقونات الصغيرة جوه الـ CSS بس.
المصادر
- RFC 4648 — The Base16, Base32, and Base64 Data Encodings (المرجع الرسمي للترميز والجدول): datatracker.ietf.org/doc/html/rfc4648
- MDN Web Docs — Base64 (الشرح العملي وتطبيقات المتصفح وdata URIs): developer.mozilla.org/en-US/docs/Glossary/Base64
- Python docs — base64 module (توثيق دوال b64encode و b64decode): docs.python.org/3/library/base64.html