base64_encode() 將二進位資料轉為 ASCII 字串,體積膨脹約 33%,但能安全穿越純文字協定(Email、JSON、XML、URL)。本文涵蓋核心 API、串流處理大檔、三大實戰場景與效能替代方案。
// 編碼
string base64_encode(string $data): string
// 解碼
string|false base64_decode(string $data, bool $strict = false): string
$strict = true:遇到非 Base64 字元直接回傳 false(預設寬鬆模式會忽略)。ValueError。function fileToBase64(string $path): string|false {
if (!is_file($path) || !is_readable($path)) return false;
$binary = file_get_contents($path); // 適用小檔(< memory_limit)
return base64_encode($binary);
}
// 大檔串流編碼(避免記憶體爆炸)
function fileToBase64Stream(string $path, int $chunkSize = 8192): Generator {
$fp = fopen($path, 'rb');
if (!$fp) return;
while (!feof($fp)) {
$chunk = fread($fp, $chunkSize);
// Base64 需 3 字節一組,串流需自行緩衝殘餘位元組
yield base64_encode($chunk); // 簡易版:每塊獨立編碼,解碼端需對應處理
}
fclose($fp);
}
// 正確串流編碼需實作狀態機,建議用成熟庫(如 symfony/mime)
// 發送端
$payload = [
'filename' => 'report.pdf',
'mime' => 'application/pdf',
'data' => base64_encode(file_get_contents('report.pdf')),
];
$ch = curl_init('https://api.partner.com/upload');
curl_setopt_array($ch, [
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => json_encode($payload),
CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
CURLOPT_RETURNTRANSFER => true,
]);
$resp = curl_exec($ch);
// 接收端
$input = json_decode(file_get_contents('php://input'), true);
$binary = base64_decode($input['data']);
file_put_contents("/storage/{$input['filename']}", $binary);
優點:JSON 原生支援、無需 multipart 解析、防火牆友善。
缺點:體積 +33%、CPU 編解碼開銷、無法串流處理超大檔。
// 寫入
$stmt = $pdo->prepare('INSERT INTO avatars (user_id, mime, data_base64) VALUES (?, ?, ?)');
$stmt->execute([$uid, 'image/png', base64_encode(file_get_contents($_FILES['avatar']['tmp_name']))]);
// 讀取並輸出
$row = $pdo->query("SELECT mime, data_base64 FROM avatars WHERE user_id=$uid")->fetch();
header("Content-Type: {$row['mime']}");
echo base64_decode($row['data_base64']);
// 或直接輸出 Data URI(前端
)
echo '
';
適用:小圖示、QR Code、簽名檔(< 100KB)。
大檔請存檔案系統/物件存儲,資料庫只存路徑。
// 產生授權碼
$payload = json_encode(['uid' => 123, 'exp' => time() + 86400*365, 'features' => ['pro', 'api']]);
$license = base64_encode($payload); // 發給客戶
// 驗證端
$decoded = json_decode(base64_decode($license), true);
if ($decoded['exp'] < time()) exit('Expired');
if (!in_array('pro', $decoded['features'])) exit('Feature not allowed');
警告:Base64 非加密,任何人可解碼竄改。生產環境請用 非對稱簽名:
// 簽名
$privateKey = openssl_pkey_get_private(file_get_contents('private.pem'));
openssl_sign($payload, $signature, $privateKey, OPENSSL_ALGO_SHA256);
$license = base64_encode($payload) . '.' . base64_encode($signature);
// 驗證
[$payloadB64, $sigB64] = explode('.', $license, 2);
$publicKey = openssl_pkey_get_public(file_get_contents('public.pem'));
$valid = openssl_verify($payloadB64, base64_decode($sigB64), $publicKey, OPENSSL_ALGO_SHA256);
| 檔案大小 | 建議做法 |
|---|---|
| < 1 MB | base64_encode(file_get_contents($path)) 直覺簡潔 |
| 1 MB ~ 100 MB | 分塊讀取 + 串流編碼(自行緩衝 3 字節對齊)或 symfony/mime |
| > 100 MB | 勿用 Base64,改用 multipart/form-data、預簽名 URL、物件存儲 SDK |
function base64url_encode(string $data): string {
return rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
function base64url_decode(string $data): string {
$pad = strlen($data) % 4;
if ($pad) $data .= str_repeat('=', 4 - $pad);
return base64_decode(strtr($data, '-_', '+/'));
}
// 用於 JWT、URL 參數、Cookie 值
file_get_contents 一次載入整檔 → 改串流或增加 memory_limit。base64_decode($str, true) 嚴格模式檢查。rawurlencode 或放入 UTF-8 JSON 字串。Base64 是「二進位轉文字」的通用膠水,適合小檔案、文字協定傳輸、Data URI 內嵌。大檔案、高併發、安全敏感場景請改用串流上傳、物件存儲、非對稱簽名。記住:Base64 不等於加密,體積 +33%,CPU 有開銷。