0

在我的 PHP 应用程序中,我使用Postmarks 的入站挂钩接收邮件。该服务接收邮件并将其 JSON 编码发送到我服务器上的 URL,这工作正常。

我遇到的问题是,当邮件的附件超过 10MB 时。

这导致

PHP致命错误:允许的内存大小为104857600字节已用尽(试图分配1821693字节)

我在这一行中所做的是:

$in = json_decode(file_get_contents("php://input"));

我有两个问题:

  1. 有没有办法提高内存效率?
  2. 为什么 10MB 邮件会失败,而内存限制实际上是 100MB?Base64 + JSON 编码是否会产生比原始大小大 10 倍的开销?

使用 memory_get_usage() 调试后编辑

Script start
47MB memory usage.
$in = file_get_contents("php://input");
63MB memory usage.
json_decode($in);
PHP terminates, due to memory size exhausted.

有趣的是,脚本已经开始使用 47MB 的内存,而没有发出任何命令。我想这是由于输入数据大吗?也许是因为 PHP 将它存储在 $HTTP_RAW_POST_DATA 中?

我可以使用任何 php.ini 指令来让 PHP 创建更少的变量吗?

4

1 回答 1

2

电子邮件附件存储为base64,所以实际的电子邮件正文大约会大2倍,所以我们有20mb

json_encode(在发件人端)也可以添加base64开销,因此单个file_get_contents调用我们可以有大约40mb,然后json_decode将需要大约20mb,添加一些局部变量,至少1个循环 - 100mb用完

我建议您阅读:memory_get_usage - 使用它来跟踪 php 分配内存的位置

然后使用unsetgc_collect_cycles

更新: 我不确定为什么 json_decode 需要这么多内存(可能是一些错误,更新 php?),无论如何在 php.ini

register_globals = off
register_long_arrays = Off
register_argc_argv = Off
auto_globals_jit = On
always_populate_raw_post_data = Off

你第二个问题:base64

因此,符合 MIME 的 Base64 编码二进制数据的实际长度通常约为原始数据长度的 137%

JSON 不应该增加很大的开销,但是将邮件正文额外编码为 json 可能会再次使用 base64

于 2013-10-18T20:34:07.150 回答