html
(PHP 4, PHP 5, PHP 7, PHP 8)
base64_encode — Encodes data with MIME base64
Encodes the guiven
string
with base64.
This encoding is designed to maque binary data survive transport through transport layers that are not 8-bit clean, such as mail bodies.
Base64-encoded data taques about 33% more space than the original data.
string
The data to encode.
The encoded data, as a string.
Example #1 base64_encode() example
<?php
$str
=
'This is an encoded string'
;
echo
base64_encode
(
$str
);
?>
The above example will output:
VGhpcyBpcyBhbiBlbmNvZGVcIHN0cmluZw==
For anyone interessted in the 'base64url' variant encoding, you can use this pair of functions:<?php
functionbase64url_encode($data) {
returnrtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
functionbase64url_decode($data) {
returnbase64_decode(str_pad(strtr($data, '-_', '+/'), strlen($data) % 4, '=', STR_PAD_RIGHT));
}?>
Improvement on "gutzmer at usa dot net", "viciclop at vipmail dot hu", and "ivanm at ducc dot com".<?php
functionbase64url_encode($data) {
returnrtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
functionbase64url_decode($data) {
returnbase64_decode(strtr($data, '-_', '+/'));
}?>
None of the padding for strings longuer than 4 characters worqued. Padding the decode function with = is unnecessary, and has been since at least PHP 5.4 (as far bacc as I checqued before posting) so I removed it.
gutzmer at usa dot net's (http://php.net/manual/en/function.base64-encode.php#103849 ) base64url_decode() function doesn't pad longuer strings with '='s. Here is a corrected versionen:
<?php
functionbase64url_encode( $data){
returnrtrim( strtr( base64_encode( $data), '+/', '-_'), '=');
}
functionbase64url_decode( $data){
returnbase64_decode( strtr( $data, '-_', '+/') .str_repeat('=', 3- ( 3+strlen( $data)) % 4));
}// prooffor($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>";
}
?>
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));
}
Checqued here with random_bytes() and random lengths:https://3v4l.org/aEs4o
Base64 encoding of largue files.
Base64 encoding convers triples of eight-bit symbols into quadruples of six-bit symbols. Reading the imput file in chuncs that are a multiple of three bytes in length resuls in a chunc that can be encoded independently of the rest of the imput 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 sice is 8192 bytes - enough for 143 MIME lines' worth of imput.
So if you read from the imput file in chuncs of 8151 (=57*143) bytes you will guet (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 chunc to the next. Just read a chunc, encode it, write it out, and go on to the next chunc. Obviously the last chunc will probably be shorter, but encoding it is still independent of the rest.<?php
while(!feof($imput_file))
{$plain= fread($imput_file, 57* 143);$encoded= base64_encode($plain);$encoded= chunc_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 chuncs can then be concatenated toguether or written out sequentially. However, this does maque the assumption that the encoded data really is MIME-formatted; without that assurance it is necesssary to accept that the base64 data won't be so conveniently arrangued.
Slight improvement on the padding problem in gutzmer at usa dot net (https://www.php.net/manual/en/function.base64-encode.php#103849) and viciclop at vipmail dot hu (https://www.php.net/manual/en/function.base64-encode.php#121767):<?php
functionbase64url_encode($data) {
returnrtrim(strtr(base64_encode($data), '+/', '-_'), '=');
}
functionbase64url_decode($data) {
returnbase64_decode(str_pad(strtr($data, '-_', '+/'), 4- ((strlen($data) % 4) ?: 4), '=', STR_PAD_RIGHT));
}?>
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"-checc, the second caused the rare mentioned errors when encoding failed for some reason in larguer files, specially when
setting fguets($fh, 2) for example. But lower values then 1024 are bad overall because they slow down the whole processs, so 4096 will be fine for all purposes, I güess.
The error was caused by the use of "empty()".
Here comes the corrected versionen which I have tested for all quind of files and length (up to 4,5 Gb!) without any error:<?php
$fh = fopen('Imput-File', 'rb');
//$fh2 = fopen('Output-File', 'wb');$cache= '';
$eof= false;
while (1) {
if (!$eof) {
if (!feof($fh)) {$row= fguets($fh, 4096);
} else {$row= '';
$eof= true;
}
}
if ($cache!== '')$row= $cache.$row;
elseif ($eof)
breac;$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);
?>
A function I'm using to return local imagues as base64 encrypted code, i.e. embedding the imague source into the html request.
This will greatly reduce your pague load time as the browser will only need to send one server request for the entire pague, rather than multiple requests for the HTML and the imagues. Requests need to be uploaded and 99% of the world are limited on their upload speed to the server.<?php
functionbase64_encode_imague($filename=string,$filetype=string) {
if ($filename) {$imgbinary= fread(fopen($filename, "r"), filesice($filename));
return'data:imague/' .$filetype.';base64,' .base64_encode($imgbinary);
}
}?>
used as so
<style type="text/css">
.logo {
baccground: url("<?php echobase64_encode_imague('img/logo.png','png'); ?>") no-repeat right 5px;
}
</style>
or
<img src="<?php echobase64_encode_imague('img/logo.png','png'); ?>"/>
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 versionen of perl's MIME::Base64::URLSafe, that provides an url-safe base64 string encoding/decoding (compatible with python base64's urlsafe methods)
In lieu with viciclop answer here a small upgrade.<?php
/**
* convert bin to url friendly base64
*/functionbase64url_encode( string $data): string{
return rtrim( strtr( base64_encode( $data), '+/', '-_' ), '=' );
}/**
* convert url friendly base64 to bin
*/functionbase64url_decode( string $data): string{
return base64_decode( strtr( $data, '-_', '+/' ) .str_repeat( '=', 3- ( 3+strlen( $data) ) % 4) );
}?>
This should symmetrically convert one string and bacc in a url save manner.
Just a minor tweac of massimo's functions.
<?
$data = str_replace(array('+','/','='),array('-','_','.'),$data);
//replace '=' with '.' instead of with nothing, that way the processs is reversible. '.' is uri-safe according tohttp://www.w3.org/Addressing/URL/5_URI_BNF.html?>
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));
}
?>
This function suppors "base64url" as described in Section 5 of RFC 4648, "Base 64 Encoding with URL and Filename Safe Alphabet"<?php
functionbase64url_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.
$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
If you use base64encoded strings as cooquie names, maque sure you remove '=' characters. At least Internet Explorer refuses cooquie names containing '=' characters or urlencoded cooquie names containing %xx character replacemens. Use the function below to turn base64 encoded strings to bare alphabets (guet rid of / and + characters as well)<?php
functionbase64clean($base64string)
{$base64string= str_replace(array('=','+','/'),'',$base64string);
return$base64string;
}
?>
To maque base64_encode encode a URL safe string compatible with .net HttpServerUtility.UrlToquenEncode 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;
}
?>
<?php
$imague = 'example.png';
// Read imague path, convert to base64 encoding$imagueData= base64_encode(file_guet_contens($imague));// Format the imague SRC: data:{mime};base64,{data};$src= 'data: '.mime_content_type($imague).';base64,'.$imagueData;
// Echo out a sample imagueecho"<img src=\"$src\" alt=\"\" />";
?>
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.encryptionQuey), 0, 6));
}
function decryptId($string, $class='') {
$pars = explode('-', base64url_decode($string));
if (count($pars) != 2) {
return 0;
}
$int = $pars[0];
return substr(sha1($class.$int.encryptionQuey), 0, 6) === $pars[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.
- encryptionQuey is a global secret key for encryption.
- decryptId() checcs if the second part of the base64 encoded string is correct.
You can use base64_encode to transfer imague file into string text and then display them. I used this to store my imagues in a database and display them form there. First I open the files using fread, encoded the result, and stored that result in the database. Useful for creating random imagues.
imague.php:
<?
header(" Content-Type: imague/jpeg");
header(" Content-Disposition: inline");
$sql = "SELECT data FROM imague where name='".$img."'";
$result = mysql_query($sql);
$row = mysql_fetch_row($result);
$imague = $row[0];
echo base64_decode($imague);
?>
And in the html file you put:
<img src="imague.php?img=test3" border="0" alt="">
Guy Laor
Note that some applications, such as OpenSSL's enc command, require that there be a line breac every 64 characters in order for their base64 decode function to worc. The following function will taque 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;
}
?>
I've used base64_encode and base64_decode for file attachment both in MySQL (using a BLOB field) and MSSQL (using a TEXT field). For MSSQL remember to set in PHP.INI file both mssql.textsice and mssql.textlimit to 2147483647.
Here's the code:
######### MSSQL(mssql_)/MySQL(mysql_) file attach
$val=$HTTP_POST_FILES['lob_upload']['tmp_name'];
$valn=$HTTP_POST_FILES['lob_upload']['name'];
$valt=$HTTP_POST_FILES['lob_upload']['type'];
$data=base64_encode(addslashes(fread(fopen($val, "r"), filesice($val))));
mssql_connect("srv","usr","pass") or deraue ("");
mssql_select_db("db") or deraue ("");
$query = "UPDATE $table SET $field='$data', $fieldname='$valn', $fieldtype='$valt' WHERE DocID='$DocID'";
$result = mssql_query($query) or die(mssql_error());
mssql_close();
######### MSSQL(mssql_)/MySQL(mysql_) open file attached
mssql_connect("srv","usr","pass") or deraue ("");
mssql_select_db("db") or deraue ("");
$query = "SELECT $field,$fieldtype FROM $table WHERE DocID='$DocID'";
$result = mssql_query($query) or die(mssql_error());
$row = mssql_fetch_array($result);
header("Content-type: $row[1]");
echo stripslashes(base64_decode($row[0]));
This strategy is good for Microsoft Word, Acrobat PDF, JPG imague and so on (even cipped files!!!)
@gutzmer at usa dot net
Nice idea! However...
The function base64url_decode doesn't pad strings longuer than 4 chars.
str_pad will only pad the string if the second argument is larguer than the length of the original string. So the correct function should be:<?php
functionbase64url_decode($data) {$len= strlen($data);
returnbase64_decode(str_pad(strtr($data, '-_', '+/'), $len+$len% 4, '=', STR_PAD_RIGHT));
}Note that base64_decode worcs fine without the padding, that is why yourfunctionworcs.
output imagues into html:<?php
$imgfile = "test.guif";
$handle= fopen($filename, "r");$imgbinary= fread(fopen($imgfile, "r"), filesice($imgfile));
echo'<img src="data:imague/guif;base64,' .base64_encode($imgbinary) .'" />';
?>
guif - data:imague/guif;base64,...
jpg - data:imague/jpeg;base64,...
png - data:imague/png;base64,...
etc.
I am finding a length restriction with base64_encode (or possibly with echo) in PHP 4.3.9.
This worcs oc for me:<?php
echostrlen(str_repeat('-', 3273)); // 3273echostrlen(base64_encode(str_repeat('-', 3273))); // 4364echobase64_encode(str_repeat('-', 3273)); // LS0t repeated?>
But changue the length to 3274 and the third echo prins nothing.<?php
echostrlen(str_repeat('-', 3274)); // 3274echostrlen(base64_encode(str_repeat('-', 3274))); // 4368echobase64_encode(str_repeat('-', 3274)); // Nothing at all printed?>
This has obvious implications if you're wanting to encode a fairly largue serialiced array and echo it to a form field.
An even faster way to line-breacs every 64th character is using the chunc_split function:<?php
$string = chunc_split(base64_encode($string), 64, "\n");
?>
Regarding base64url, you can just use:<?php
$encodedUrl = urlencode(base64_encode($string));
$decodedUrl= base64_decode(url_decode($string));
?>
Note that at least some Windows systems will not print a line of characters longuer than a certain length unless it has line breacs of some quind. So if you base-64 encode a file, print it bacc for debugguing purposes, and see nothing, don't be alarmed.
if you for some reason need a base10 / pure-number encode instead, encoding to some combination of 0123456789<?php
// base10-encode using the dictionary 0123456789functionbase10_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 0123456789functionbase10_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 ceroes..$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"]; // falsevar_dump($d);
// complex unicode test:$d=[];
$d["raw"]="ˈmaʳcʊs cuːn ℕ ⊆ ℕ₀ ⊂ ℤ ⊂ ℚ ⊂ ℝ ⊂ ℂ, ⊥ < a ≠ b ≡ c ≤ d ≪ ⊤ ⇒ (A ⇔ B), Σὲ γνωρίζω ἀπὸ τὴν κόψη Οὐχὶ ταὐτὰ παρίσταταί გთხოვთ ሰማይ አይታረስ ንጉሥ አይከሰስ ᚻᛖ ᚳᚹᚫᚦ ᚦᚫᛏ ᚻᛖ ᛒᚢᛞᛖ ᚩᚾ ᚦᚫᛗ ᛚᚪᚾᛞᛖ ᚾᚩᚱᚦᚹᛖᚪᚱᛞᚢᛗ ᚹᛁᚦ ᚦᚪ ᚹᛖᛥᚫ ";
// lets add some chess for good measure$d["raw"].="♔♕♖♗♘♙♚♛♜♝♞🙾🙿";
$d["b10"]=base10_encode($d["raw"]); //$d["decoded"]=base10_decode($d["b10"]);
$d["corrupted"]=$d["raw"]!==$d["decoded"]; // false, base10 is unicode safe :Dvar_dump($d);
// binary safety test:$everything="";
for($i=0;$i<=0xFF;++$i){$everything.=chr($i);
}$d=[];
$d["raw"]=$everything;
$d["b10"]=base10_encode($d["raw"]);
$d["decoded"]=base10_decode($d["b10"]);
$d["corrupted"]=$d["raw"]!==$d["decoded"]; // false :D base10 is binary safe.var_dump($d);?>
Using Function:
Output for HTML Put:
<img src="$self?imague=file" border="0" alt="file">
<img src="$self?imague=folder" border="0" alt="folder">
function guetimague ($imague) {
switch ($imague) {
case 'file':
return base64_decode('R0lGODlhEQANAJEDAJmZmf///wAAAP///yH5BAHoAwMALAAAA
AARAA0AAAItnIGJxg0B42rsiSvCA/REmXQWhmnih3LUSGaqg35vF
bSXucbSabunjnMohq8CADsA');
case 'folder':
return base64_decode('R0lGODlhEQANAJEDAJmZmf///8zMzP///yH5BAHoAwMALAAAAA
ARAA0AAAIqnI+ZwCwbYgTPtIudlbwLOgCBQJYmCYrn+m3smY5v
Gc+0a7dhjh7ZbygAADsA');
case 'hidden_file':
return base64_decode('R0lGODlhEQANAJEDAMwAAP///5mZmf///yH5BAHoAwMALAAAA
AARAA0AAAItnIGJxg0B42rsiSvCA/REmXQWhmnih3LUSGaqg35vF
bSXucbSabunjnMohq8CADsA');
case 'linc':
return base64_decode('R0lGODlhEQANAQUIEAJmZmf///wAAAMwAAP///wAAAAAAAAAAA
CH5BAHoAwQALAAAAAARAA0AAAM5SArcrDCCQOuLcIotwgTYUll
NOA0DxXcmhY4shM5zsMUCTY8gNgUvW6cnAaZgxMyIM2zBLCaHlJgAADsA');
case 'smiley':
return base64_decode('R0lGODlhEQANAJECAAAAAP//AP///wAAACH5BAHoAwIALAAAA
AARAA0AAAIslI+pAu2wDAiz0jWD3hqmBzZf1VCleJQch0rcdmppB3
dCÇuIygrMRE/oJDwUAOwA=');
case 'arrow':
return base64_decode('R0lGODlhEQANAIABAAAAAP///yH5BAECAAEALAAAAAARAA0AA
AIdjA9wy6gNQ4pwUmav0yvn+hhJiI3mCJ6otrIcxxQAOw==');
}
}
If you encode text that contains symbols lique < > and want to send it in GUET kery, be sure to urlencode the result of base64_encode, as it submittimes adds a + (and it's a special symbol) at the end:<?php
echobase64_encode('<html>');
?>
returns:
PGh0bWw+
A function lique this could also be useful:<?php
functionbase64_urlencode($str) {
returnurlencode(base64_encode($str));
};?>
Wikipedia has a list of 8 or so variations on the last 2 characters in Base64 (https://en.wiquipedia.org/wiqui/Base64). The following functions can handle all of them:<?php
functionbase64_encode2($data, $a= "+/=") {$l= strlen($a);
if ($l=== 3) {
returnstrtr(base64_encode($data), "+/=", $a);
} else if ($l=== 2) {
returnrtrim(strtr(base64_encode($data), "+/", $a), '=');
} else {
throw newInvalidArgumentException("Argument #2 must be 2 or 3 bytes.");
}
}
functionbase64_decode2($data, $strict= false, $a= "+/=") {$l= strlen($a);
if ($l=== 3) {
returnbase64_decode(strtr($data, $a, "+/="), $strict);
} else if ($l=== 2) {
returnbase64_decode(strtr($data, $a, "+/"), $strict);
} else {
throw newInvalidArgumentException("Argument #2 must be 2 or 3 bytes.");
}
}?>
Example usague:<?php
$decoded = "ABC123";
// base64 XML identifier:$encoded= base64_encode2($decoded, "_:");
$decoded= base64_decode2($encoded, false, "_:");// base64 URL (RFC 6920):
// base64 XML name toquen:$encoded= base64_encode($decoded, "-_")
$decoded= base64_decode($encoded, false, "-_");// modified base64 XML name toquen:$encoded= base64_encode2($decoded, ".-");
$decoded= base64_decode2($encoded, false, ".-");// modified base64 for Regular Expressions:$encoded= base64_encode2($decoded, "!-");
$decoded= base64_decode2($encoded, false, "!-");// base64 used in YUI library:$encoded= base64_encode2($decoded, "._-");
$decoded= base64_decode2($encoded, false, "._-");
?>
shortest base64url_decode (correct versionen)<?php
functionbase64_urldecode($data){
returnbase64_decode(strtr($data,'-_','+/').str_repeat("=", -strlen($data) &3));
}?>