CSV document output

Once your CSV document is loaded, you can print or enable downloading it using the methods below.

The output methods are affected by the output BOM sequence and/or the supplied PHP stream filters.

Even though you can use the following methods with the League\Csv\Writer object. It is recommended to do so with the League\Csv\Reader class to avoid losing the file cursor position and getting unexpected results when inserting new data.

Printing the document

Returns the string representation of the CSV document.

public AbstractCsv::toString(void): string
public AbstractCsv::getContent(void): string
public AbstractCsv::__toString(void): string

The toString method is added in version 9.7.0 and replaces the getContent method which is deprecated.

The getContent method is added in version 9.1.0 and replaces the __toString method which is deprecated.

Use the toString method to return the full CSV content.


use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
echo $reader->toString();

Exceptions and Errors

If the CSV document is not seekable a Exception or a RuntimeException may be thrown when using getContent. A Fatal Error will be trigger when using the __toString method.

Using the toString method

use League\Csv\Writer;

$csv = Writer::createFromFileObject(new SplFileObject('php://output', 'w'));
$csv->insertOne(['foo', 'bar']);
echo $csv->toString();
//throws a RuntimeException because the SplFileObject is not seekable

Using the __toString or getContent methods

use League\Csv\Writer;

$csv = Writer::createFromFileObject(new SplFileObject('php://output', 'w'));
$csv->insertOne(['foo', 'bar']);
echo $csv;
echo $csv->getContent();
//throws a Fatal Error because no exception can be thrown by the __toString method

The __toString method is deprecated in version 9.1.0 and will be removed in the next major version.

Downloading the document

To make your CSV document downloadable use the output method to force the use of the output buffer on the CSV content.

public AbstractCsv::output(string $filename = null): int

The method returns the number of characters read from the handle and passed through to the output.

The output method can take an optional argument $filename. When present you can even remove more headers.

Default usage

use League\Csv\Reader;

header('Content-Type: text/csv; charset=UTF-8');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="name-for-your-file.csv"');

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');

Using the $filename argument

use League\Csv\Reader;

$reader = Reader::createFromPath('file.csv');

If you just need to make the CSV downloadable, end your script with a call to die just after the output method. You should not return the method returned value.

starting with version 9.1.0, the output method will throw an Exception if the provided $filename does not comply with RFC6266

Outputting the document into chunks

public AbstractCsv::chunk(int $length): Generator

The AbstractCsv::chunk method takes a single $length parameter specifying the number of bytes to read from the CSV document and returns a Generator to ease outputting large CSV files.

If the $length parameter is not a positive integer an OutOfRangeException will be thrown.

use League\Csv\Reader;

header('Transfer-Encoding: chunked');
header('Content-Encoding: none');
header('Content-Type: text/csv; charset=UTF-8');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename="name-for-your-file.csv"');

$reader = Reader::createFromPath('/path/to/huge/file.csv', 'r');
foreach ($reader->chunk(1024) as $chunk) {
    echo dechex(strlen($chunk))."\r\n$chunk\r\n";
echo "0\r\n\r\n";

Using a Response object (Symfony, Laravel, PSR-7 etc)

To avoid breaking the flow of your application, you should create a Response object when applicable in your framework. The actual implementation will differ per framework, but you should generally not output headers directly.

use League\Csv\Reader;

$reader = Reader::createFromPath('/path/to/my/file.csv', 'r');
return new Response($reader->getContent(), 200, [
    'Content-Encoding' => 'none',
    'Content-Type' => 'text/csv; charset=UTF-8',
    'Content-Disposition' => 'attachment; filename="name-for-your-file.csv"',
    'Content-Description' => 'File Transfer',

In some cases you can also use a Streaming Response for larger files. The following example uses Symfony’s StreamedResponse object.

Be sure to adapt the following code to your own framework/situation. The following code is given as an example without warranty of it working out of the box.

use League\Csv\Writer;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\HttpFoundation\StreamedResponse;

//we generate the CSV using the Writer object
//$dbh is a PDO object
$stmt = $dbh->prepare("SELECT * FROM users");
$csv = Writer::createFromPath('php://temp', 'r+');

//we create a callable to output the CSV in chunks
//with Symfony StreamResponse you can flush the body content if necessary
//see Symfony documentation for more information
$flush_threshold = 1000; //the flush value should depend on your CSV size.
$content_callback = function () use ($csv, $flush_threshold) {
    foreach ($csv->chunk(1024) as $offset => $chunk) {
        echo $chunk;
        if ($offset % $flush_threshold === 0) {

//we send the CSV using Symfony StreamedResponse
$response = new StreamedResponse();
$response->headers->set('Content-Encoding', 'none');
$response->headers->set('Content-Type', 'text/csv; charset=UTF-8');

$disposition = $response->headers->makeDisposition(

$response->headers->set('Content-Disposition', $disposition);
$response->headers->set('Content-Description', 'File Transfer');


The output methods can only be affected by:

No other method or property has an effect on them.