PHP 8.3.0 RC 6 available for testing

base64_encode

(PHP 4, PHP 5, PHP 7, PHP 8)

base64_encode使用 MIME base64 对数据进行编码

说明

base64_encode(string $string): string

使用 base64 对 string 进行编码。

设计此种编码是为了使二进制数据可以通过非纯 8-bit 的传输层传输,例如电子邮件的主体。

Base64-encoded 数据要比原始数据多占用 33% 左右的空间。

参数

string

要编码的数据。

返回值

编码后的字符串数据。

示例

示例 #1 base64_encode() 示例

<?php
$str
= 'This is an encoded string';
echo
base64_encode($str);
?>

以上示例会输出:

 
VGhpcyBpcyBhbiBlbmNvZGVkIHN0cmluZw==

参见

add a note

User Contributed Notes 37 notes

up
251
gutzmer at usa dot net
12 years ago
For anyone interested in the 'base64url' variant encoding, you can use this pair of functions:

<?php
function base64url_encode($data) {
return
rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function
base64url_decode($data) {
return
base64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}
?>
up
33
biziclop at vipmail dot hu
6 years ago
gutzmer at usa dot net's ( http://php.net/manual/en/function.base64-encode.php#103849 ) base64url_decode() function doesn't pad longer strings with '='s. Here is a corrected version:

<?php
function base64url_encode( $data ){
return
rtrim( strtr( base64_encode( $data ), '+/', '-_'), '=');
}

function
base64url_decode( $data ){
return
base64_decode( strtr( $data, '-_', '+/') . str_repeat('=', 3 - ( 3 + strlen( $data )) % 4 ));
}

// proof
for( $i = 0, $s = ''; $i < 24; ++$i, $s .= substr("$i", -1 )){
$base64_encoded = base64_encode( $s );
$base64url_encoded = base64url_encode( $s );
$base64url_decoded = base64url_decode( $base64url_encoded );
$base64_restored = strtr( $base64url_encoded, '-_', '+/')
.
str_repeat('=',
3 - ( 3 + strlen( $base64url_encoded )) % 4
);
echo
"$s<br>$base64url_decoded<br>$base64_encoded<br>$base64_restored<br>$base64url_encoded<br><br>";
}
?>
up
26
Rasmus Schultz
5 years ago
In PHP 7, the padding issue with base64_decode() is no more - the following is totally fine:

function base64_encode_url($string) {
return str_replace(['+','/','='], ['-','_',''], base64_encode($string));
}

function base64_decode_url($string) {
return base64_decode(str_replace(['-','_'], ['+','/'], $string));
}

Checked here with random_bytes() and random lengths:

https://3v4l.org/aEs4o
up
19
Hayley Watson
10 years ago
Base64 encoding of large files.

Base64 encoding converts triples of eight-bit symbols into quadruples of six-bit symbols. Reading the input file in chunks that are a multiple of three bytes in length results in a chunk that can be encoded independently of the rest of the input file. MIME additionally enforces a line length of 76 characters plus the CRLF. 76 characters is enough for 19 quadruples of six-bit symbols thus representing 19 triples of eight-bit symbols. Reading 57 eight-bit symbols provides exactly enough data for a complete MIME-formatted line. Finally, PHP's default buffer size is 8192 bytes - enough for 143 MIME lines' worth of input.

So if you read from the input file in chunks of 8151 (=57*143) bytes you will get (up to) 8151 eight-bit symbols, which encode as exactly 10868 six-bit symbols, which then wrap to exactly 143 MIME-formatted lines. There is no need to retain left-over symbols (either six- or eight-bit) from one chunk to the next. Just read a chunk, encode it, write it out, and go on to the next chunk. Obviously the last chunk will probably be shorter, but encoding it is still independent of the rest.

<?php

while(!feof($input_file))
{
$plain = fread($input_file, 57 * 143);
$encoded = base64_encode($plain);
$encoded = chunk_split($encoded, 76, "\r\n");
fwrite($output_file, $encoded);
}

?>

Conversely, each 76-character MIME-formatted line (not counting the trailing CRLF) contains exactly enough data for 57 bytes of output without needing to retain leftover bits that need prepending to the next line. What that means is that each line can be decoded independently of the others, and the decoded chunks can then be concatenated together or written out sequentially. However, this does make the assumption that the encoded data really is MIME-formatted; without that assurance it is necessary to accept that the base64 data won't be so conveniently arranged.
up
18
MitMacher
14 years ago
Unfortunately my "function" for encoding base64 on-the-fly from 2007 [which has been removed from the manual in favor of this post] had 2 errors!
The first led to an endless loop because of a missing "$feof"-check, the second caused the rare mentioned errors when encoding failed for some reason in larger files, especially when
setting fgets($fh, 2) for example. But lower values then 1024 are bad overall because they slow down the whole process, so 4096 will be fine for all purposes, I guess.
The error was caused by the use of "empty()".

Here comes the corrected version which I have tested for all kind of files and length (up to 4,5 Gb!) without any error:

<?php
$fh
= fopen('Input-File', 'rb');
//$fh2 = fopen('Output-File', 'wb');

$cache = '';
$eof = false;

while (
1) {

if (!
$eof) {
if (!
feof($fh)) {
$row = fgets($fh, 4096);
} else {
$row = '';
$eof = true;
}
}

if (
$cache !== '')
$row = $cache.$row;
elseif (
$eof)
break;

$b64 = base64_encode($row);
$put = '';

if (
strlen($b64) < 76) {
if (
$eof) {
$put = $b64."\n";
$cache = '';
} else {
$cache = $row;
}

} elseif (
strlen($b64) > 76) {
do {
$put .= substr($b64, 0, 76)."\n";
$b64 = substr($b64, 76);
} while (
strlen($b64) > 76);

$cache = base64_decode($b64);

} else {
if (!
$eof && $b64{75} == '=') {
$cache = $row;
} else {
$put = $b64."\n";
$cache = '';
}
}

if (
$put !== '') {
echo
$put;
//fputs($fh2, $put);
//fputs($fh2, base64_decode($put)); // for comparing
}
}

//fclose($fh2);
fclose($fh);
?>
up
21
luke at lukeoliff.com
12 years ago
A function I'm using to return local images as base64 encrypted code, i.e. embedding the image source into the html request.

This will greatly reduce your page load time as the browser will only need to send one server request for the entire page, rather than multiple requests for the HTML and the images. Requests need to be uploaded and 99% of the world are limited on their upload speed to the server.

<?php
function base64_encode_image ($filename=string,$filetype=string) {
if (
$filename) {
$imgbinary = fread(fopen($filename, "r"), filesize($filename));
return
'data:image/' . $filetype . ';base64,' . base64_encode($imgbinary);
}
}
?>

used as so

<style type="text/css">
.logo {
background: url("<?php echo base64_encode_image ('img/logo.png','png'); ?>") no-repeat right 5px;
}
</style>

or

<img src="<?php echo base64_encode_image ('img/logo.png','png'); ?>"/>
up
8
massimo dot scamarcia at gmail dot com
17 years ago
function urlsafe_b64encode($string) {
$data = base64_encode($string);
$data = str_replace(array('+','/','='),array('-','_',''),$data);
return $data;
}

function urlsafe_b64decode($string) {
$data = str_replace(array('-','_'),array('+','/'),$string);
$mod4 = strlen($data) % 4;
if ($mod4) {
$data .= substr('====', $mod4);
}
return base64_decode($data);
}

Php version of perl's MIME::Base64::URLSafe, that provides an url-safe base64 string encoding/decoding (compatible with python base64's urlsafe methods)
up
1
ivanm at duck dot com
1 year ago
Slight improvement on the padding problem in gutzmer at usa dot net (/manual/en/function.base64-encode.php#103849) and biziclop at vipmail dot hu (/manual/en/function.base64-encode.php#121767):

<?php
function base64url_encode($data) {
return
rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function
base64url_decode($data) {
return
base64_decode(str_pad(strtr($data, '-_', '+/'), 4 - ((strlen($data) % 4) ?: 4), '=', STR_PAD_RIGHT));
}
?>
up
1
Daniel Klein
1 year ago
Improvement on "gutzmer at usa dot net", "biziclop at vipmail dot hu", and "ivanm at duck dot com".

<?php
function base64url_encode($data) {
return
rtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}

function
base64url_decode($data) {
return
base64_decode(strtr($data, '-_', '+/'));
}
?>

None of the padding for strings longer than 4 characters worked. Padding the decode function with = is unnecessary, and has been since at least PHP 5.4 (as far back as I checked before posting) so I removed it.
up
1
dawgeatschikin at hotmail dot com
17 years ago
Just a minor tweak of massimo's functions.

<?
$data = str_replace(array('+','/','='),array('-','_','.'),$data);
//replace '=' with '.' instead of with nothing, that way the process is reversible. '.' is uri-safe according to http://www.w3.org/Addressing/URL/5_URI_BNF.html
?>
up
0
Tom
16 years ago
This function supports "base64url" as described in Section 5 of RFC 4648, "Base 64 Encoding with URL and Filename Safe Alphabet"

<?php
function base64url_encode($plainText)
{
$base64 = base64_encode($plainText);
$base64url = strtr($base64, '+/', '-_');
return (
$base64url);
}
?>

You may wish to rtrim (or escape) trailing ='s for use in a URI.
up
-1
Naser Mirzaei
9 years ago
<?php
$image
= 'example.png';

// Read image path, convert to base64 encoding
$imageData = base64_encode(file_get_contents($image));

// Format the image SRC: data:{mime};base64,{data};
$src = 'data: '.mime_content_type($image).';base64,'.$imageData;

// Echo out a sample image
echo "<img src=\"$src\" alt=\"\" />";
?>
up
0
php at ianco dot co dot uk
17 years ago
I am finding a length restriction with base64_encode (or possibly with echo) in PHP 4.3.9.
This works ok for me:
<?php
echo strlen(str_repeat('-', 3273)); // 3273
echo strlen(base64_encode(str_repeat('-', 3273))); // 4364
echo base64_encode(str_repeat('-', 3273)); // LS0t repeated
?>
But change the length to 3274 and the third echo prints nothing.
<?php
echo strlen(str_repeat('-', 3274)); // 3274
echo strlen(base64_encode(str_repeat('-', 3274))); // 4368
echo base64_encode(str_repeat('-', 3274)); // Nothing at all printed
?>
This has obvious implications if you're wanting to encode a fairly large serialized array and echo it to a form field.
up
0
massimo dot scamarcia at gmail dot com
17 years ago
$data = str_replace(array('+','/','='),array('-','_',),$data); // MIME::Base64::URLSafe implementation

$data = str_replace(array('+','/'),array('-','_'),$data); // Python raise "TypeError: Incorrect padding" if you remove "=" chars when decoding
up
0
Gabriel Malca
17 years ago
If the function doesn't exist, this is a messy but effective way of doing it:

<?

echo bencode("Gabriel Malca");
// R2FicmllbCBNYWxjYQ==

function bencode($string='') {
$binval = convert_binary_str($string);
$final = "";
$start = 0;
while ($start < strlen($binval)) {
if (strlen(substr($binval,$start)) < 6)
$binval .= str_repeat("0",6-strlen(substr($binval,$start)));
$tmp = bindec(substr($binval,$start,6));
if ($tmp < 26)
$final .= chr($tmp+65);
elseif ($tmp > 25 && $tmp < 52)
$final .= chr($tmp+71);
elseif ($tmp == 62)
$final .= "+";
elseif ($tmp == 63)
$final .= "/";
elseif (!$tmp)
$final .= "A";
else
$final .= chr($tmp-4);
$start += 6;
}
if (strlen($final)%4>0)
$final .= str_repeat("=",4-strlen($final)%4);
return $final;
}

function convert_binary_str($string) {
if (strlen($string)<=0) return;
$tmp = decbin(ord($string[0]));
$tmp = str_repeat("0",8-strlen($tmp)).$tmp;
return $tmp.convert_binary_str(substr($string,1));
}

?>
up
0
juha at kuhazor dot idlegames dot com
19 years ago
If you use base64encoded strings as cookie names, make sure you remove '=' characters. At least Internet Explorer refuses cookie names containing '=' characters or urlencoded cookie names containing %xx character replacements. Use the function below to turn base64 encoded strings to bare alphabets (get rid of / and + characters as well)

<?php
function base64clean($base64string)
{
$base64string = str_replace(array('=','+','/'),'',$base64string);

return
$base64string;
}
?>
up
-1
Gerard
10 years ago
To make base64_encode encode a URL safe string compatible with .net HttpServerUtility.UrlTokenEncode function use this:

<?php
url_safe_base64_encode
($string)
{
#First base64 encode
$data = base64_encode($string);

#Base64 strings can end in several = chars. These need to be translated into a number
$no_of_eq = substr_count($data, "=");
$data = str_replace("=", "", $data);
$data = $data.$no_of_eq;

#Then replace all non-url safe characters
$data = str_replace(array('+','/'),array('-','_'),$data);
return
$data;
}
?>
up
-1
ozziez_box at hotmail dot com
5 years ago
Regarding base64url, you can just use:

<?php
$encodedUrl
= urlencode(base64_encode($string));
$decodedUrl = base64_decode(url_decode($string));
?>
up
-1
eric [at] d512 [dot] com
16 years ago
Note that at least some Windows systems will not print a line of characters longer than a certain length unless it has line breaks of some kind. So if you base-64 encode a file, print it back for debugging purposes, and see nothing, don't be alarmed.
up
-2
Andi
15 years ago
I needed a simple way to obfuscate auto_increment primary keys in databases when they are visible to users in URIs or API calls. The users should not be able to increment the id in the URL and see the next data record in the database table.

My solution (uses modified base64 functions by Tom):

function base64url_encode($plainText) {

$base64 = base64_encode($plainText);
$base64url = strtr($base64, '+/=', '-_,');
return $base64url;
}

function base64url_decode($plainText) {

$base64url = strtr($plainText, '-_,', '+/=');
$base64 = base64_decode($base64url);
return $base64;
}

function encryptId($int, $class='') {

return base64url_encode($int.'-'.substr(sha1($class.$int.encryptionKey), 0, 6));
}

function decryptId($string, $class='') {

$parts = explode('-', base64url_decode($string));
if (count($parts) != 2) {

return 0;
}

$int = $parts[0];
return substr(sha1($class.$int.encryptionKey), 0, 6) === $parts[1]
? (int)$int
: 0;
}

- The optional 2nd argument is the class name, so two equal ids of different tables will not result in two equal obfuscated ids.

- encryptionKey is a global secret key for encryption.

- decryptId() checks if the second part of the base64 encoded string is correct.
up
-1
jonb at wobblymusic dot com
14 years ago
Note that some applications, such as OpenSSL's enc command, require that there be a line break every 64 characters in order for their base64 decode function to work. The following function will take care of this problem:

<?php
function ($encodeMe) {
$data = base64_encode($encodeMe);
$datalb = "";
while (
strlen($data) > 64) {
$datalb .= substr($data, 0, 64) . "\n";
$data = substr($data,64);
}
$datalb .= $data;
return
$datalb;
}
?>
up
-3
andronick(dot)mail(dog)gmail(dot)com
13 years ago
output images into html:

<?php

$imgfile
= "test.gif";

$handle = fopen($filename, "r");

$imgbinary = fread(fopen($imgfile, "r"), filesize($imgfile));

echo
'<img src="data:image/gif;base64,' . base64_encode($imgbinary) . '" />';

?>

gif - data:image/gif;base64,...
jpg - data:image/jpeg;base64,...
png - data:image/png;base64,...
etc.
up
-1
divinity76 at gmail dot com
2 years ago
if you for some reason need a base10 / pure-number encode instead, encoding to some combination of 0123456789

<?php
// base10-encode using the dictionary 0123456789
function base10_encode(string $str): string
{
$ret = "";
for (
$i = 0, $imax = strlen($str); $i < $imax; ++ $i) {
$ret .= str_pad((string) ord($str[$i]), 3, "0", STR_PAD_LEFT);
}
return
$ret;
}
// base10-decode using the dictionary 0123456789
function base10_decode(string $str): string
{
$ret = "";
for (
$i = 0, $imax = strlen($str); $i < $imax; $i += 3) {
// notably here we are using (int) to trim away the zeroes..
$ret .= chr((int) substr($str, $i, 3));
}
return
$ret;
}
?>

it is unicode-safe and binary-safe, testing:

<?php
// simple ascii test:
$d=[];
$d["raw"]="test";
$d["b10"]=base10_encode($d["raw"]); // 116101115116
$d["decoded"]=base10_decode($d["b10"]); // test
$d["corrupted"]=$d["raw"]!==$d["decoded"]; // false
var_dump($d);
// complex unicode test:
$d=[];
$d["raw"]="ˈmaʳkʊs kuːn ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B), Σὲ γνωρίζω ἀπὸ τὴν κόψη Οὐχὶ ταὐτὰ παρίσταταί გთხოვთ ሰማይ አይታረስ ንጉሥ አይከሰስ ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ ";
// lets add some chess for good measure
$d["raw"].="♔♕♖♗♘♙♚♛♜♝♞