thephpleague/csv

Getting error "Cannot modify header information - headers already sent by" when trying to download a DB in chunks

scottsuhy opened this issue · 1 comments

Laravel: 8.83.25 PHP: 3.4 CSV: 9.8

My database is too large to download without getting memory errors from NGINX/PHP, so I'm trying to break up the CSV into chunks of 10,000 records, but I'm getting an error from $csv->output($filename);

[2023-01-26 17:14:13] local.ERROR: Cannot modify header information - headers already sent by (output started at C:\Apache24\htdocs\cannabis\vendor\league\csv\src\AbstractCsv.php:326) {"userId":1,"exception":"[object] (ErrorException(code: 0): Cannot modify header information - headers already sent by (output started at C:\Apache24\htdocs\cannabis\vendor\league\csv\src\AbstractCsv.php:326) at C:\Apache24\htdocs\cannabis\vendor\league\csv\src\AbstractCsv.php:358)

In reading StackOverflow they say "Functions that send/modify HTTP headers must be invoked before any output is made. Otherwise the call fails"

How do I save queries into multiple CSVs? Here is my current function:

public function export_weightrecords(){   
	$count = weightrecords::count();                 

	for($i = 0; $i < $count; $i = $i + 10000){
		
		$csv = Writer::createFromFileObject(new \SplTempFileObject);

		$query = weightrecords::query()->skip($i)->take(1000);
		$query = $query->orderBy('id');        
		$records = $query->get();               
		
		if(isset($records[0])){
			$csv[$j]->insertOne(array_keys($records[0]->getAttributes()));
			foreach ($records as $record) {
				$csv->insertOne($record->toArray());
			}
			$csv->insertOne(['']);
		}
		
		$filename = "export_weightrecords_" . $i . date('_Y_m_d_H_i_s') . ".csv";            
		$csv->output($filename);	
	}
}

@scottsuhy thanks for using the library.

As explain in the documentation when using the package in the context of a framework you should try to use the framework way of generating streaming response and not use the package way because then you indeed end up with the error message you have.

I hope the example in the documentation will give you some hints into how to solve your current issue.