Laravel-datatables: Exportación del lado del servidor 200000 registros

Creado en 31 mar. 2018  ·  19Comentarios  ·  Fuente: yajra/laravel-datatables

Resumen del problema o solicitud de función

Cuando 200000 registra cómo exportar datos. Cuando exporto datos "Se agotó el tamaño de memoria permitido de 134217728 bytes", se produjo esta excepción.

¿Qué otras opciones hay para exportar una gran cantidad de datos en yajra / datatable?

Proporcione una forma diferente de exportar una gran cantidad de datos.

Tenemos una cantidad limitada de RAM en el servidor.

Fragmento de código del problema

public function showData(ServiceDataTable $dataTable)
    {
        return $dataTable
            ->render('dataTable.renderDataTable');
    }

Detalles del sistema

  • Sistema operativo: Ubuntu 16.04
  • Versión de PHP: 7.0.0
  • Versión de Laravel: 5.5
  • Versión de Laravel-Datatables: 8.0
  • Botones de Laravel-Datatables Versión: 3.1
performance question

Todos 19 comentarios

Debe implementar su propio generador de archivos de Excel para manejar esta solicitud masiva. En su clase ServiceDataTable, puede anular el método protected function buildExcelFile() y tal vez hacer algo, etc. Consulte los documentos de laravel-excel para obtener más información.

    /**
     * Build excel file and prepare for export.
     *
     * <strong i="7">@return</strong> \Maatwebsite\Excel\Writers\LaravelExcelWriter
     */
    protected function buildExcelFile()
    {
        /** <strong i="8">@var</strong> \Maatwebsite\Excel\Excel $excel */
        $excel = app('excel');

        return $excel->create($this->getFilename(), function (LaravelExcelWriter $excel) {
            $excel->sheet('exported-data', function (LaravelExcelWorksheet $sheet) {
                $sheet->fromArray($this->getDataForExport());
            });
        });
    }

Creo que el siguiente código crea una excepción
$this->getDataForExport();
Obtiene una excepción cuando se define o usa editColumn() del lado del servidor
hay 200000 registros.
¿Existe alguna otra forma de obtener datos sin procesar o sin asignar más memoria?
Tengo el siguiente enlace pero yajra yajra / laravel-datatables-buttons: ^ 3.1 pero no es compatible con Laravel / Excel: 3.0
https://laravel-excel.maatwebsite.nl/docs/3.0/export/queued

Debe haber una forma de exportar directamente desde la consulta o de forma elocuente.

Utilizo Postman para imitar esa operación pero

Se agotó el tamaño de memoria permitido de 134217728 bytes

excepción lanzada. No tengo filas que solían generar html, utilizo rawColumns () para escapar de html, mi consulta tarda 0.420 ms en phpmyadmin y al principio 1.4 seg.

Si podemos poner esto en cola, también deberíamos poder guardarlo en una carpeta en el servidor y luego proporcionar el enlace al usuario para descargarlo.

Gracias por la respuesta.

Lo estoy usando en JQuery Datatable o yajra datatable y quiero exportar desde el lado del servidor.

Creo que no es posible guardarlo en una carpeta en el servidor, hay muchos problemas que generarán problemas.

Necesito transmisión de datos.

La cantidad de datos tiene un tamaño de respuesta de 20 MB o más.

Mi requisito es similar, pero me gustaría guardar el archivo en el servidor (o S3) y dar un enlace para descargarlo en el panel de mi aplicación o en el correo electrónico. Veo la posibilidad de hacer esto, si encuentro algo lo actualizaré aquí.

Tengo un problema con el procesamiento del lado del servidor que consume una gran cantidad de RAM y el tamaño de asignación de memoria del script predeterminado es de 60 MB.
Mira memory_limit en php.ini
El límite de tiempo de ejecución max_execution_time es 60.
Después de aumentar el valor, pudo realizar una solicitud utilizando la exportación del lado del servidor.

Modifiqué la función de Excel para almacenar el archivo en lugar de descargarlo, está almacenando el archivo en almacenamiento / exportaciones / carpeta.

public function excel()
{
    $this->buildExcelFile()->store('xls');
}

Actualmente no tengo una gran cantidad de datos en mi entorno de desarrollo, ¿puede hacer el cambio anterior en su configuración y ver si es capaz de crear el Excel en esa carpeta sin tocar el límite de memoria?

Otra cosa a tener en cuenta es que estoy usando Laravel 5.1, por lo tanto, maatwebsite / excel versión 2.1

Lo que realmente quiero hacer es poner esto en cola y volver a la página con un mensaje de que la creación del informe está en progreso y el enlace para descargar el archivo se enviará por correo electrónico a su identificación registrada "

en la versión 2.1 no estoy seguro de cómo poner en cola, pero encontré esto donde usan " Queued Chunk ", pero no estoy seguro de cómo implementar esto.

Entonces, ¿alguna actualización sobre esto?

Entonces, ¿alguna actualización sobre esto?

Si alguien usa Laravel Excel 3.0+, la solución superior no funcionará. por lo que debe anular buildExcelFile() utilizando "Exportación en cola" .

O hice algo más usando fragmentación también pero creando mi rasgo y uso CSV para hacer mi trabajo y este es un ejemplo

alguna actualización ?

A partir de Laravel 6, puede usar LazyCollections para cargar solo un elemento a la vez en la memoria. Esto soluciona el problema de quedarse sin memoria.

Solo es necesario extender la clase DataTable y escribir un DataTablesExportHandler adaptado.

Mira mi esencia

¡Disfrutar!

@singhofmarco ¿Puedes dar un ejemplo?

@singhofmarco Estoy de acuerdo, comencé un proyecto v10 el año pasado que utilizará LazyCollections pero no puede continuarlo en cajeros automáticos.

Tomé una ruta diferente. He anulado la función csv, llamando a DataTables con una página de datos cada vez, fragmentándolos de manera efectiva. Usando fputcsv en las filas de resultados hasta que el archivo esté completo, luego devuelva el contenido del archivo en una Respuesta de Laravel.

No solo nunca más se alcanza el límite de memoria (hasta que el propio CSV crece más allá del límite de memoria de PHP, entonces una respuesta de transmisión podría ayudar más), sino que también es más del doble de rápido ...

@ameenross si es posible, puede compartir su código por favor.

@karmendra Preferiría no hacerlo, ya que es para una versión anterior de Yajra Datatables. Pero básicamente lo que estoy haciendo es fusionar algunos valores de página y longitud en la solicitud, llamar al código que normalmente devuelve una página de datos para AJAX ( $this->ajax()->getData(true)['data'] en mi caso). Tengo una clase base para tablas de datos que extiende la clase Yajra Datatable, con una función getCsv (después de todo, decidí no anular la función CSV, pero eso no es importante). Esto sigue un bucle hasta que no quedan más páginas.

@ameenross Gracias por eso es útil. Le daré una oportunidad a esto.

Tabla de datos de Laravel :: v1.5.0
Aquí está mi solución basada en el comentario de @TheGeekyM , la dejo en caso de que ayude a alguien más.
Creé una clase ChunkedDatatableExportHandler que implementa FromQuery y luego anulo el método buildExcelFile en mis ServiceDataTables para usarlo.

<?php

namespace App\DataTables;

use Yajra\DataTables\Services\DataTable;

class ServiceDataTable extends DataTable
{
  protected $exportClass = ChunkedDatatableExportHandler::class;

  protected function buildExcelFile()
  {
      $query = app()->call([$this, 'query']);
      $query = $this->applyScopes($query);

      $dataTable = app()->call([$this, 'dataTable'], compact('query'));
      $dataTable->skipPaging();
      $data_query = $dataTable->getFilteredQuery();

      return new $this->exportClass($data_query);
  }
}
<?php
namespace App\DataTables;

use Illuminate\Database\Query\Builder;
use Maatwebsite\Excel\Concerns\Exportable;
use Maatwebsite\Excel\Concerns\FromQuery;
use Maatwebsite\Excel\Concerns\WithHeadings;

class ChunkedDatatableExportHandler implements FromQuery, WithHeadings
{
    use Exportable;

    /**
     * <strong i="11">@var</strong> Builder 
     */
    protected $query;

    /**
     * ChunkDatatablesExportHandler constructor.
     * <strong i="12">@param</strong> Builder $query
     */
    public function __construct(Builder $query)
    {
        $this->query = $query;
    }

    /**
     * <strong i="13">@return</strong> array
     */
    public function headings(): array
    {
        $first = $this->query()->first();

        if ($first) {
            return array_keys((array)$first);
        }

        return [];
    }

    /**
     * <strong i="14">@return</strong> Builder
     */
    public function query()
    {
        return $this->query;
    }
}
¿Fue útil esta página
0 / 5 - 0 calificaciones

Temas relacionados

FilipeBorges1993 picture FilipeBorges1993  ·  3Comentarios

hari-web picture hari-web  ·  3Comentarios

SGarridoDev picture SGarridoDev  ·  3Comentarios

kamrava picture kamrava  ·  3Comentarios

vipin733 picture vipin733  ·  3Comentarios