Laravel-excel: 已用完 134217728 字节的允许内存大小

创建于 2018-07-19  ·  22评论  ·  资料来源: Maatwebsite/Laravel-Excel

先决条件

  • [X] 能够重现代码之外的行为,问题与 Laravel Excel 隔离。
  • [X] 检查您的问题是否尚未提交。
  • [X] 检查是否没有提交解决此问题的 PR。

版本

  • PHP 版本:7.1.13
  • Laravel 版本:5.6
  • 包版本:^3.0

描述

当我尝试使用FromQuery选项导出时,我收到了Allowed memory size of 134217728 bytes exhausted

重现步骤

预期行为:

我想解决我的问题:)

实际行为:

附加信息

namespace App\Exports;

use App\OldTransaction;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Http\Request;
use jDate;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\ShouldAutoSize;
use Maatwebsite\Excel\Concerns\WithHeadings;
use Maatwebsite\Excel\Concerns\WithMapping;

class OldDepositExport implements FromQuery, ShouldQueue, WithMapping, WithHeadings, ShouldAutoSize
{
    use Exportable;

    /**
     * DepositExport constructor.
     * <strong i="27">@param</strong> Request $request
     */
    public function __construct(Request $request)
    {
    }

    public function headings(): array
    {
        return [
            'ID',
        ];
    }


    public function map($transaction): array
    {
        return [
            $transaction->id,
        ];
    }

    public function query()
    {
        return User::query()
            ->where('status', '=', 1)
            ->select(['id']);
    }
}

查看此图片https://i.imgur.com/yMgUqXP.jpg

最有用的评论

你期待谁的回答?

我们的软件是免费和开源的,这意味着我们软件的使用是可选的。 我们不承担任何责任,也没有义务支持。 我们将尽最大努力提供支持。

如果您在商业上使用该软件并需要精心支持或迫切需要它,我们可以在商业基础上提供。 请联系[email protected]或通过电话 +31 (0)10 744 9312。

所有22条评论

谁能帮我?

4天。 没有答案 :-(

你期待谁的回答?

我们的软件是免费和开源的,这意味着我们软件的使用是可选的。 我们不承担任何责任,也没有义务支持。 我们将尽最大努力提供支持。

如果您在商业上使用该软件并需要精心支持或迫切需要它,我们可以在商业基础上提供。 请联系[email protected]或通过电话 +31 (0)10 744 9312。

好的,所以请不要关闭这个问题。 也许有人可以解决这个问题。

谢谢

我认为是php内存的问题,可能是数据太多导致内存溢出……和库没有关系。

@jlcarpioe我有将近 20 万行。 将行附加到工作表时出现问题

您是否尝试在 php.ini 中最大化 memory_limit?

@ bagana89这不是一个好的解决方案

我无法重现您的问题。 我可以使用您共享的代码导出 30 万行的用户表。 请注意,每项作业的内存使用量都会增加,因为 PhpSpreadsheet 必须打开每次都变大的工作簿。 为这个进程分配更多的内存并没有错。 似乎您没有分配很多内存,这就是它溢出如此之快的原因。

最好删除ShouldAutoSize因为这将重新计算每个作业中的工作簿列尺寸。 这比不使用它需要更多的内存。

我分配了 1 GB 的内存,但结果仍然与 saeedvaziry 相同。
刚刚从 v2.1 迁移到 v3.1。 v2.1 也有同样的问题,这促使我迁移,但没有解决问题。 Excel::create 在 v2.1 中也更容易设置输出样式。

似乎在导出(使用 FromQuery)时分块效果不佳(使用大量内存 - 对我来说最多 3 Gigs 大约 200k 记录)。 但是使用分块导入可以正常工作。 (内存不超过 50MB)

我只有 15,000 条记录并给了我同样的错误。 我能做什么?

这是错误:

[2019-11-24 22:39:59] local.ERROR: 允许的内存大小为 134217728 字节已用完(尝试分配 18874368 字节){"exception":"[object] (Symfony\Component\Debug\Exception\FatalErrorException(代码:1):在 C:\wamp64\www\.....\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Collection\Cells.php:421 中允许的内存大小为 134217728 字节(试图分配 18874368 字节) )
[堆栈跟踪]

0 {主要}

"}

您需要增加 php.ini 中允许的内存限制或使用 ini_set 动态设置

我有,我有 1G 但它不起作用

运行进程时,php-cli进程消耗了多少内存? 那么它必须超过1Gig

内存限制绝对不是问题。 根据 phpinfo 设置为 4GB,我仍然有这个问题。

我有同样的问题

“解决方案”会将您的文件拆分为多个文件,释放它们之间的内存,然后合并所有文件并将合并的文件作为响应发送。

缺点:

  • 为临时文件提供更多空间
  • 花费更多时间(非智能循环)
  • 需要更多代码(非开箱即用)

优点:

  • 有用

同样的问题,内存限制为 512 MB,4K 行

最终解决方案
这是旧的,但现在阅读本文的人应该知道
如果您正在导入或导出 ToModel 或 ToCollection,则该过程需要大量内存分配才能转换
将数据转换为可用的形式,如集合或数组。

在这种情况下,不要实现 ToModel 或 ToCollect,您需要绕过流程并通过实现 OnEachRow 手动执行操作
它允许您实现将传入 Excel Row 对象的 onRow 方法。 您可以实现 WithHeadingRow 以将其结构化为关联数组。
使用此 $row->toArray() 获取您的数据并根据需要对其进行处理。 这是快速且易于操作的。

PS:如果仍然出现内存限制错误,只需像这样在最后一行添加一个return语句
返回;

谢谢你

我遇到了同样的问题,根据@MoFoLuWaSo的建议,我将 +128Mb 的内存使用量减少到 54Mb。

1) 实施 DTO。 这减少了最多的内存使用量。
2) 对 DTO 的属性进行排序并删除withMapping
3)删除ShouldAutoSize

@saeedvz 的情况下,它应该是这样的:

namespace App\DataTransferObjects;

class OldDepositRow
{
    public int $id;
    public string $created_at;
}

namespace App\Exports;

use App\DataTransferObjects\OldDepositRow;

class OldDepositExport implements FromCollection, ShouldQueue, WithHeadings
{
    use Exportable;

    public function headings(): array
    {
        return [
            'ID',
        ];
    }

    public function collection()
    {
        $users = User::query()
            ->where('status', '=', 1)
            ->select(['id']);

        return $users->map(
           function ($user) {
                $row = new OldDepositRow();
                $row->transaction_id = $user->transaction->id;

                // cast objects like Carbon or BigDecimal to string
                $row->created_at = $user->transaction->created_at->format('d-m-Y');

                return $row;
            }
        );
    }
}
此页面是否有帮助?
0 / 5 - 0 等级