[PROMOÇÃO] Assine com + 30% de desconto ANUAL MENSAL (últimas horas)
Thiago Luna de Melo
Criador Thiago Luna de Melo 29/08/2024

Olá, Mestre!

Seguindo essa aula de upload de arquivo, qual um bom caminho para upar um csv contendo mais de 50k linhas com dados de alunos para dar uma carga inicial no novo sistema EAD?

Uma vez feito o upload, tem como, por exemplo, com algum tipo de chunk, ler o csv em pedaços de 1000 em 1000 linhas e pra cada pedaço, chamar um job passando um array com essas 1000 linhas pra ele dar insert no bd?

 

No Laravel tem como eu fazer esse chunk de csv?

Seria bom ter um job pra fazer esse chunk e, pra cada pedaço, chamar outro job pra processar os dados e salvar no bd?

Manager Carlos Ferreira 29/08/2024

Olá, Thiago! Como vai?

Use filas para fazer isso, com filas você pode jogar o processo inteiro para um job e deixar ele rodar, mas ainda é mais recomendado quebrar em partes e processar pedaços por pedaços.

Pra ler um arquivo com muitas linhas, eu trabalharia com php generators (isso ajuda no controle de memória).

Ou, você pode no loop mesmo de leitura do arquivo criando jobs com partes do array (10 itens por exemplo) e jogando para um job ir processando.

Pegou a ideia amigo?

Carlos Ferreira
Criador Thiago Luna de Melo 29/08/2024

Entendi a ideia.

 Sobre quebrar em pedaços, seria criar vários csv menores e processar eles?

Thiago Luna de Melo
Manager Carlos Ferreira 29/08/2024

Não seria necessário, vc pode criando arrays com partes do conteúdo, e a cada loop vai zerando o array logo após enviar para o job processar.

Carlos Ferreira
Criador Thiago Luna de Melo 29/08/2024

Entendi, mestre.

A lógica principal ficou assim:

 /**
*
@param Request $request
* @return JsonResponse
*/
public function uploadCsv(Request $request): JsonResponse
{
// Valida o upload
$request->validate([
'csv_file' => 'required|mimes:csv|max:2048',
]);

// Armazena o arquivo CSV
$filePath = $request->file('csv_file')->store('csv_files');
$handle = fopen(storage_path('app/' . $filePath), "r");

// Lê o arquivo CSV com Generator PHP pra evitar uso excessivo de memória
$generator = $this->readCsv($handle);

// Faz Split dos dados para processá-los em grupos de N elementos
$groupSize = 1000;
$currentGroup = [];
foreach ($generator as $value) {
// Adicionar o valor atual ao grupo
$currentGroup[] = $value;

// Se o grupo atingir o tamanho desejado, processa o grupo
if (count($currentGroup) === $groupSize) {
$this->processCsv($currentGroup);

// Resetar o array de grupo
$currentGroup = [];
}
}

// Se restarem elementos no array, adicionar sozinhos
if (count($currentGroup) > 0) {
$this->processCsv($currentGroup);
}

return response()->json(['message' => 'CSV processado com sucesso.']);
}

/**
* @param $handle
* @param string $delimeter
* @return false|Generator
*/
function readCsv($handle, string $delimeter = ','): false|Generator
{
$header = [];
$row = 0;

if ($handle === false) {
return false;
}

while (($data = fgetcsv($handle, 0, $delimeter)) !== false) {

if ($row == 0) {
$header = $data;
} else {
# on demand usage
yield $data;
}

$row++;
}
fclose($handle);
}

private function processCsv(array $data)
{
// Disparar um Job pra salvar os dados no bd
}


A ideia agora é organizar esses métodos em Jobs.
O primeiro Job seria pra ler o csv upado e fazer o split, onde pra cada grupo de dados chamar um segundo job pra processá-los.

Faz sentido?

Thiago Luna de Melo
Manager Carlos Ferreira 29/08/2024

Sim, faz sentido, porque assim vc joga essa lógica para o JOB que faz o split dos dados.

Carlos Ferreira
Sabe a Solução? Ajude a resolver!

Precisa estar logado para conseguir responder a este ticket!

Clique Aqui Para Entrar!