i have a system that saves files to the server harddrive in base 64 encoded after stripping them from email files.
i would like to change the file to thier original format again, how can i do that in php?
this is how i tried to save the files but that does not seem to create a valid files:
$start = $part['starting-pos-body'];
$end = $part['ending-pos-body'];
$len = $end-$start;
$written = 0;
$write = 2028;
$body = '';
while ($start <= $end) {
fseek($this->stream, $start, SEEK_SET);
$my = fread($this->stream, $write);
fwrite($temp_fp, base64_decode($my));
$start += $write;
}
fclose($temp_fp);
@traylz makes the point clear for why it may fail when it shouldn't. However, base64_decode()
may fail for large images even. I have worked with 6 to 7 MB files fine, I haven't gone over this size, so for me it should be as simple as:
$dir = dirname(__FILE__);
// get the base64 encoded file and decode it
$o_en = file_get_contents($dir . '/base64.txt');
$d = base64_decode($o_en);
// put decoded string into tmp file
file_put_contents($dir . '/base64_d', $d);
// get mime type (note: mime_content_type() is deprecated in favour
// for fileinfo functions)
$mime = str_replace('image/', '.', mime_content_type($dir . '/base64_d'));
rename($dir . '/base64_d', $dir . '/base64_d' . $mime);
If the following fails try adding chunk_split()
function to decode operation:
$d = base64_decode(chunk_split($o_en));
So what am I sayaing...forget the loop unless there is a need for it...keep the orignal file extension if you don't trust php's mime detection. use chunk_split()
on base64_decode()
operation if working on large files.
NOTE: all theory so untested
EDIT: for large files that mostly likely will freeze file_get_contents()
, read in what you need, output to file so little RAM is used:
$chunkSize = 1024;
$src = fopen('base64.txt', 'rb');
$dst = fopen('binary.mime', 'wb');
while (!feof($src)) {
fwrite($dst, base64_decode(fread($src, $chunkSize)));
}
Your problem is that you read 2028 chunks, checking start<=end AFTER you read chunk,so you read beyond end pointer, and you should check < insead of <= (to avoid reading 0 bytes)
Also you don't need to fseek on every iteration, because fread reads from current position. You can take fssek out of loop( before while).Why 2028 btw? Try this out:
fseek($this->stream, $start, SEEK_SET);
while ($start < $end) {
$write = min($end-$start,2048);
$my = fread($this->stream, $write);
fwrite($temp_fp, base64_decode($my));
$start += $write;
}
fclose($temp_fp);
thank you all guys for the help finally i ended up with:
shell_exec('/usr/bin/base64 -d '.$temp_file.' > '.$temp_file.'_s');