note 75788 deleted from function.base64-encode by danbrown

From: Date: Fri, 07 Aug 2009 22:05:28 +0000
Subject: note 75788 deleted from function.base64-encode by danbrown
References: 1  Groups: php.notes 
Request: Send a blank email to php-notes+get-159201@lists.php.net to get a copy of this message
Note Submitter: MitMacher ---- Recently I have got the problem to sent emails over SMTP with big attachments (up to 16Mb). Memory_limit is set to 8M, post_max_size and upload_max_filesize are set to 16M, so the file-upload (html-form) does work but the necessary encoding of that file exceeds the memory limit (of course): <?php $data = chunk_split(base64_encode(file_get_contents($tmp_file)), 76, "\n"); ?> This is bad, so I searched for a way to do that splitting/encoding stuff on-the-fly (row by row) so that I do not have to keep the whole file data in memory. Unfortunately I cound not find any function on the web, so I decided to write it on my own and here is the result: <?php $fh = fopen('Input-File', 'rb'); //$fh2 = fopen('Output-File', 'wb'); $cache = ''; $eof = false; while (1) { if (!$eof) { if (!feof($fh)) { $row = fgets($fh); } else { $row = ''; $eof = true; } } if (!empty($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 ($b64{75} == '=') { $cache = $row; } else { $put = $b64."\n"; $cache = ''; } } if (!empty($put)) { echo $put; //fputs($fh2, $put); //fputs($fh2, base64_decode($put)); // for comparing } } //fclose($fh2); fclose($fh); ?> I have tested this (and the decoding!) with several binary and text files up to 1Gb (without echo *g*) and it works great. The only thing I am wondering about is the read-length of the fgets() function. The default is 1024 which works fine and it should also work with smaller values like 512 or even 2. But this is true only for small files (some kb), the bigger the file the more errors came up. So the valid minimum seems to be 1024 and maybe more (4096?) on very large files, I dont know. I have also tested fread() but it works even more worse, I also dont know why... The other way around it is much more simple: only some base64_decode()s row by row and all has done.

« previous php.notes (#159201) next »