Laravel-excel: Taille de mémoire autorisée de 134217728 octets épuisée

Créé le 19 juil. 2018  ·  22Commentaires  ·  Source: Maatwebsite/Laravel-Excel

Conditions préalables

  • [X] Capable de reproduire le comportement en dehors de votre code, le problème est isolé à Laravel Excel.
  • [X] Vérifié que votre problème n'est pas déjà classé.
  • [X] Coché si aucun PR n'a été soumis pour résoudre ce problème.

Versions

  • Version PHP : 7.1.13
  • Version Laravel : 5.6
  • Version du package : ^3.0

La description

Je reçois Allowed memory size of 134217728 bytes exhausted lorsque j'essaie d'exporter avec l'option FromQuery

Étapes pour reproduire

Comportement prévisible:

Je veux résoudre mon problème :)

Comportement réel :

Information additionnelle

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']);
    }
}

Voir cette image https://i.imgur.com/yMgUqXP.jpg

Commentaire le plus utile

De qui attendez-vous une réponse ?

Notre logiciel est gratuit et open source, ce qui signifie que l'utilisation de notre logiciel est facultative. Nous n'assumons aucune responsabilité et il n'y a aucune obligation de soutien. Nous fournirons un soutien sur la base de nos meilleurs efforts.

Si vous utilisez le logiciel à des fins commerciales et avez besoin d'une assistance élaborée ou en avez besoin de toute urgence, nous pouvons vous l'offrir sur une base commerciale. Veuillez contacter [email protected] ou par téléphone +31 (0)10 744 9312.

Tous les 22 commentaires

Quelqu'un peut-il m'aider?

4 jours. pas de réponse :-(

De qui attendez-vous une réponse ?

Notre logiciel est gratuit et open source, ce qui signifie que l'utilisation de notre logiciel est facultative. Nous n'assumons aucune responsabilité et il n'y a aucune obligation de soutien. Nous fournirons un soutien sur la base de nos meilleurs efforts.

Si vous utilisez le logiciel à des fins commerciales et avez besoin d'une assistance élaborée ou en avez besoin de toute urgence, nous pouvons vous l'offrir sur une base commerciale. Veuillez contacter [email protected] ou par téléphone +31 (0)10 744 9312.

OK donc s'il vous plaît ne fermez pas ce problème. peut-être que quelqu'un peut résoudre ce problème.

Merci

Je pense que c'est un problème de mémoire php, peut-être qu'il y a trop de données et déborde de mémoire... Il n'y a pas de rapport avec la librairie.

@jlcarpioe J'ai près de 200 000 lignes. Le problème se produit lors de l'ajout de lignes à la feuille

Avez-vous essayé de maximiser memory_limit dans php.ini ?

@bagana89 Ce n'est pas une bonne solution

Je ne peux pas reproduire votre problème. Je suis en mesure d'exporter une table d'utilisateurs de 300 000 lignes à l'aide du code que vous avez partagé. Notez que l'utilisation de la mémoire augmentera à chaque tâche, car PhpSpreadsheet doit ouvrir le classeur qui s'agrandit à chaque fois. Il n'y a rien de mal à affecter un peu plus de mémoire pour ce processus. Il semble que vous n'ayez pas beaucoup de mémoire assignée, c'est pourquoi elle déborde si rapidement.

Il est préférable de supprimer le ShouldAutoSize car cela recalculera les dimensions de la colonne des classeurs dans chaque travail. Cela prend beaucoup plus de mémoire que sans l'utiliser.

J'ai 1 Go de RAM alloué et j'ai toujours le même résultat que saeedvaziry.
Je viens de migrer de la v2.1 à la v3.1. J'avais le même problème avec la v2.1 qui m'a motivé à migrer, mais n'a pas résolu le problème. Excel::create dans la version 2.1 était également beaucoup plus facile à styliser la sortie.

Il semble que le découpage ne fonctionne pas bien lors de l'exportation (à l'aide de FromQuery) (utilise une énorme quantité de mémoire - jusqu'à 3 Go pour moi pour environ 200 000 enregistrements). Mais l'importation fonctionne très bien en utilisant le découpage. (la mémoire ne dépasse jamais 50 Mo)

Je n'ai que 15 000 enregistrements et m'a donné la même erreur. Que puis-je faire?

C'est l'erreur :

[2019-11-24 22:39:59] local.ERROR : taille de mémoire autorisée de 134217728 octets épuisée (tentative d'allouer 18874368 octets) {"exception":"[object] (Symfony\Component\Debug\Exception\FatalErrorException( code : 1) : taille de mémoire autorisée de 134217728 octets épuisée (tentative d'allouer 18874368 octets) à C:\wamp64\www\.....\vendor\phpoffice\phpspreadsheet\src\PhpSpreadsheet\Collection\Cells.php:421 )
[trace de la pile]

0 {principal}

"}

Vous devrez augmenter la limite de mémoire autorisée dans votre php.ini ou la définir dynamiquement en utilisant ini_set

Je l'ai fait, j'ai 1G mais ça ne marche pas

Lorsque vous exécutez le processus, combien de mémoire le processus php-cli consomme-t-il ? Il doit être supérieur à 1Gig alors

La limite de mémoire n'est certainement pas le problème. Il est réglé sur 4 Go selon phpinfo et j'ai toujours ce problème.

j'ai le même problème

Une « solution » consisterait à diviser votre fichier en plusieurs, en libérant de la mémoire entre eux, puis en fusionnant tous les fichiers et en les envoyant fusionnés en tant que réponse.

Les inconvénients.:

  • Plus d'espace pour les fichiers temporaires
  • Plus de temps passé (boucles non intelligentes)
  • Plus de code requis (non prêt à l'emploi)

Avantages.:

  • Ça marche

le même problème, la limite de mémoire est de 512 Mo, 4K lignes

Solution finale
C'est vieux, mais celui qui lit ceci maintenant devrait savoir que
si vous importez ou exportez ToModel ou ToCollection, ce processus nécessite une énorme allocation de mémoire pour convertir
les données sous des formes utilisables comme une collection ou un tableau.

Dans ce cas, n'implémentez pas ToModel ou ToCollect, vous devez contourner le processus et effectuer l'opération manuellement en implémentant OnEachRow
qui vous permet d'implémenter la méthode onRow qui passera un objet Excel Row. Vous pouvez également implémenter WithHeadingRow pour le structurer sous la forme d'un tableau associatif.
Utilisez ce $row->toArray() pour obtenir vos données et les traiter comme vous le souhaitez. C'est rapide et facile à manipuler.

PS : si vous obtenez toujours l'erreur de limite de mémoire, ajoutez simplement une instruction de retour à la dernière ligne comme celle-ci
revenir;

Merci

J'ai eu le même problème et avec les suggestions de @MoFoLuWaSo, j'ai réduit mon utilisation de la mémoire de +128 Mo à 54 Mo.

1) mettre en œuvre un DTO. C'est ce qui a le plus réduit l'utilisation de la mémoire.
2) ordonner les propriétés du DTO et supprimer withMapping
3) supprimer ShouldAutoSize

Dans le cas de @saeedvz, cela devrait ressembler à ceci :

namespace App\DataTransferObjects;

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

et

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;
            }
        );
    }
}
Cette page vous a été utile?
0 / 5 - 0 notes