2

I have a function that is streaming a csv file for the client to download. I find that after 5 seconds, the browser will terminate the connection. I have used postman and curl, and it completes the output so I can eliminate that the buffer is full / not outputting.

On firefox I get the reason:

NS_ERROR_NET_PARTIAL_TRANSFER

    public function random_stream()
    {
        ini_set('zlib.output_compression', 'Off');

        // Clear output buffering
        while (ob_get_level()) {
            ob_end_clean();
        }
        // Set headers first
        header('Content-Type: text/csv');
        header('Content-Disposition: attachment; filename="test.csv"');
        header('Pragma: no-cache');
        header('Expires: 0');

        // Now open output stream
        $file = fopen('php://output', 'w');

        // Optional: output a CSV header row
        fputcsv($file, ['Column 1', 'Column 2', 'Column 3']);

        $start_time = time();
        while ((time() - $start_time) < 10) {
            $row = [
                $this->randomString(),
                $this->randomString(),
                $this->randomString()
            ];
            fputcsv($file, $row);
            flush(); // optional but ensures streaming output
        }

        fclose($file);
        exit;
    }


    function randomString($length = 8)
    {
        $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
        $charactersLength = strlen($characters);
        $randomStr = '';
        for ($i = 0; $i < $length; $i++) {
            $randomStr .= $characters[rand(0, $charactersLength - 1)];
        }
        return $randomStr;
    }

Am I setting the headers wrong or not flushing properly for the browser to keep alive?

response headers:

check what is wrong with this response:

GET /random_stream HTTP/1.1
Host: ***obscured***
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:140.0) Gecko/20100101 Firefox/140.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br, zstd
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-Fetch-Dest: document
Sec-Fetch-Mode: navigate
Sec-Fetch-Site: none
Sec-Fetch-User: ?1
Priority: u=0, i
Pragma: no-cache
Cache-Control: no-cache

HTTP/1.1 200 OK
Transfer-Encoding: chunked
Cache-Control: no-cache
Connection: Keep-Alive
Content-Disposition: attachment; filename="test.csv"
Content-Type: text/csv;charset=UTF-8
Date: Wed, 06 Aug 2025 16:56:01 GMT
Expires: 0
Keep-Alive: timeout=5, max=100
Pragma: no-cache
Server: Apache/2.4.41 (Ubuntu)
11
  • 2
    I tested your code. I had to make some changes because your code cannot be executed as it is. I removed any OOP, and then called random_stream(). It works fine here. PHP version 8.3.24. I don't think there's anything wrong with the code in your question. So the problem could be code that's not in your question, or something on your server. Since the connection is broken it could also be your connection to the server. Commented Aug 6 at 18:39
  • 1
    Just interesting information: My server generated more than 2.75 million lines in 10 seconds. Commented Aug 6 at 18:45
  • Yeah this code looks like a stress test. What's the size of the real files you want to send? Commented Aug 6 at 18:51
  • size is small just 500kB to 1mB. The real process was running some db query and then streaming them. Since then, I have changed to an async job with polling to get the complete report which works (so I know my data querying + data normalization is not broken). However, my local dev + production is still running into this issue if I was to stream for more than 5 seconds instead of serving a completed file. Its a private web service, and on old architecture, PHP 5.6, and codeigniter 2 FYI. Commented Aug 6 at 20:15
  • I also just tested on windows firefox browser. I think something in my ubuntu OS or some sort of proxy is causing internet discconection. Commented Aug 6 at 20:18

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.