代码之家  ›  专栏  ›  技术社区  ›  Sander Marechal

如何在PHP中对大型文件进行base64解码

  •  5
  • Sander Marechal  · 技术社区  · 17 年前

    我的PHP web应用程序有一个API,可以接收相当大的文件(高达32MB),这些文件是base64编码的。目标是将这些文件写入文件系统的某个位置。当然解码了。这样做的资源密集度最低的方式是什么?

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

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

    还有其他选择吗?我可以手工做吗?或者将文件写入磁盘编码并调用一些外部命令?有什么想法吗?

    2 回复  |  直到 17 年前
        1
  •  23
  •   Evert    15 年前

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

    如果从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);
    
        2
  •  11
  •   Gumbo    17 年前

    将数据解码成更小的块。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);
    
        3
  •  1
  •   Ross Alex    5 年前

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

    1. Javascript:使用FileReader从输入读取文件,并将readAsDataURL()读取到文件变量。
    2. 发送包含UID、chunk number和chunk quantity的chunk并等待响应,然后逐个发送另一个chunk。

    写入每个块,直到最后一块。然后对流执行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);
    

    ... 现在,您的base64解码文件位于$target local path中。笔记不能读写同一个文件,因此$source和$target必须不同。

    推荐文章