此代码工作正常(但我担心它会因大型输入文件而失败)。示例一读取整个文件并且不循环,示例2读取3k块并循环直到EOF。
$in = fopen("in.b64", 'r');
$out = fopen("out.png", 'wb');
if ((!$in) || (!$out)) die ("convert: i/o error in base64 convert");
$first = true;
while (!feof($in))
{
$b64 = fread($in,filesize($in_fn));
// strip content tag from start of stream
if ($first)
{
$b64 = substr($b64,strpos($b64,',')+1);
$first = false;
}
$bin = base64_decode($b64);
if (!fwrite($out,$bin)) die("convert write error in base64 convert");
}
fclose($in);
fclose($out);
虽然此代码会产生损坏的图像:
$in = fopen("in.b64", 'r');
$out = fopen("out.png", 'wb');
if ((!$in) || (!$out)) die ("convert: i/o error in base64 convert");
$first = true;
while (!feof($in))
{
$b64 = fread($in,3072);
// strip content tag from start of stream
if ($first)
{
$b64 = substr($b64,strpos($b64,',')+1);
$first = false;
}
$bin = base64_decode($b64);
if (!fwrite($out,$bin)) die("convert write error in base64 convert");
}
fclose($in);
fclose($out);
答案 0 :(得分:1)
虽然3072可以被4整除,但是边界正确排列,你会从它的前面取出一些字符,使它不能正确对齐。另外,base64规范说每64个字符都有一个换行符,这可能会偏移对齐并破坏解析。
我的解决方案维护了一个要解码的字符缓冲区,并且一次只能获取n * 4个字符的块。作为测试,我一次读取21个字节,它似乎工作。需要注意的是,一次的字节数应该大于预期从字符串前面取下的字符(逗号)。
$in = fopen("in.b64", 'r');
$out = fopen("out.txt", 'wb');
if ((!$in) || (!$out)) die ("convert: i/o error in base64 convert");
$first = true;
$buffer = '';
while (!feof($in))
{
$b64 = preg_replace("/[\s]+/", "", fread($in,21));
// strip content tag from start of stream
if ($first)
{
$b64 = substr($b64,strpos($b64,',')+1);
$first = false;
}
$buffer .= $b64;
$length = strlen($buffer);
$leftover = $length % 4;
if ($leftover == 0)
{
$chunk = $buffer;
$buffer = '';
}
else
{
$chunk = substr($buffer, 0, -$leftover);
$buffer = substr($buffer, $length - $leftover);
}
if (!empty($chunk))
{
$bin = base64_decode($chunk);
if (!fwrite($out,$bin)) die("convert write error in base64 convert");
}
}
fclose($in);
fclose($out);