Search code examples
phplaravelvagrantmysql-workbenchinsomnia

How do i split a 6 gb CSV file into chunks using php


I'm a beginner level developer learning php.The task that i need to do is upload a 6gb CSV file which contains data, into the data base.I need to access the data i.e reading the file through controller.php file and then splitting that huge CSV file into 10,000 row output CSV files and writing data into those output CSV files. I have been through this task a week already and dint figure it out yet.Would you guys please help me in solving this issue.

<?php

namespace App\Http\Controllers;
use Illuminate\Queue\SerializesModels;

use App\User;
use DateTime;
use Illuminate\Http\Request;
use Storage;
use Validator;
use GuzzleHttp\Client;
use GuzzleHttp\RequestOptions;
use Queue;
use App\model;


class Name extends Controller
{


     public function Post(Request $request)
     {

         if($request->hasfile('upload')){
            ini_set('auto_detect_line_endings', TRUE);
                $main_input = $request->file('upload');
                $main_output = 'output';
                $filesize = 10000;
                $input = fopen($main_input,'r');
                $rowcount = 0;
                $filecount = 1;
                $output = '';

                // echo "here1";
                while(!feof($input)){
                    if(($rowcount % $filesize) == 0){
                        if($rowcount>0) { 
                            fclose($output);
                        }
                    $output = fopen(storage_path(). "/tmp/".$main_output.$filecount++ . '.csv','w');
                    }
                    $data = fgetcsv($input);
                    print_r($data);

                    if($data) {

                        fputcsv($output, $data);
                    }

                    $rowcount++;
                }
                fclose($output);
        }
     }
}  

Solution

  • Maybe it's because you are creating a new $output file handler for each iteration.

    I've made some adjustments, so that we only create a file when the rowCount = 0 and close it when the fileSize is reached. Also the rowCount has to be reset to 0 each time we close the file.

    public function Post(Request $request)
         {
    
             if($request->hasfile('upload')){
                ini_set('auto_detect_line_endings', TRUE);
                    $main_input = $request->file('upload');
                    $main_output = 'output';
                    $filesize = 10000;
                    $input = fopen($main_input,'r');
                    $rowcount = 0;
                    $filecount = 1;
                    $output = '';
    
                    // echo "here1";
                    while(!feof($input)){
                        if ($rowCount == 0) {
                            $output = fopen('php://output', storage_path(). "/tmp/".$main_output.$filecount++ . '.csv','w');
                        }
                        if(($rowcount % $filesize) == 0){
                            if($rowcount>0) { 
                                fclose($output);
                                $rowCount = 0;
                                continue;
                            }
    
                        }
                        $data = fgetcsv($input);
                        print_r($data);
    
                        if($data) {
    
                            fputcsv($output, $data);
                        }
    
                        $rowcount++;
                    }
                    fclose($output);
            }
         }