7

我的 PHP Web 应用程序有一个 API,可以接收经过 base64 编码的相当大的文件(最大 32 MB)。目标是将这些文件写入我的文件系统的某个位置。当然是解码。什么是最不占用资源的方法?

编辑:通过 API 接收文件意味着我的 PHP 应用程序中有一个 32MB 的字符串,而不是磁盘某处的 32MB 源文件。我需要将该字符串解码到文件系统上。

使用 PHP 自己的 base64_decode() 并没有减少它,因为它使用大量内存,所以我一直遇到 PHP 的内存限制(我知道,我可以提高这个限制,但我对允许 PHP 使用 256MB 左右感觉不好每个进程)。

还有其他选择吗?我可以手动做吗?还是将文件编码写入磁盘并调用一些外部命令?任何想法?

4

3 回答 3

23

尽管这有一个公认的答案,但我有一个不同的建议。

如果您从 API 中提取数据,则不应将整个有效负载存储在变量中。使用 curl 或其他 HTTP 提取器,您可以自动将数据存储在文件中。

假设您通过一个简单的 GET url 获取数据:

$url = 'http://www.example.com/myfile.base64';
$target = 'localfile.data';

$rhandle = fopen($url,'r');
stream_filter_append($rhandle, 'convert.base64-decode');

$whandle = fopen($target,'w');

stream_copy_to_stream($rhandle,$whandle);
fclose($rhandle);
fclose($whandle);

好处:

  • 应该更快(减少大量变量的复制)
  • 很少的内存开销

如果您必须从临时变量中获取数据,我可以建议这种方法:

$data = 'your base64 data';
$target = 'localfile.data';

$whandle = fopen($target,'w');
stream_filter_append($whandle, 'convert.base64-decode',STREAM_FILTER_WRITE);

fwrite($whandle,$data);

fclose($whandle);
于 2009-05-21T20:51:00.707 回答
11

以更小的块解码数据。Base64 数据的四个字符等于“Base256”数据的三个字节。

因此,您可以将每个 1024 个字符分组并将它们解码为 768 个八位字节的二进制数据:

$chunkSize = 1024;
$src = fopen('base64.data', 'rb');
$dst = fopen('binary.data', 'wb');
while (!feof($src)) {
    fwrite($dst, base64_decode(fread($src, $chunkSize)));
}
fclose($dst);
fclose($src);
于 2009-05-20T15:05:16.637 回答
1

传输 32Mb 字符串不是一个好主意。但我有一个适合我的任务的解决方案,它可以接受从浏览器到应用服务器的任何大小的文件。算法: 客户端

  1. Javascript:使用 FileReader 和 readAsDataURL() 从 INPUT 读取文件到 FILE var。
  2. 将 FILE 中的所有数据从开头剪切到第一个“,”位置,将其与 array_chunks 拆分为 max_upload_size/max_post_size php var。
  3. 发送带有 UID、块编号和块数量的块并等待响应,然后一个接一个地发送另一个块。

服务器端 写入每个块,直到最后一个。然后用流做base64:

$src = fopen($source, 'r');
$trg = fopen($target, 'w');
stream_filter_append($src, 'convert.base64-decode');
stream_copy_to_stream($src, $trg);
fclose($src);
fclose($trg);

...现在您在 $target 本地路径中有您的 base64 解码文件。笔记!你不能读写同一个文件,所以 $source 和 $target 必须不同。

于 2021-01-05T15:30:35.020 回答