1

I want to "pipe" a file through PHP.

My PHP script calls a bash script through "shell_exec". The bash script downloads a file and prints its data. The PHP script then continues to send the file as response:

if (!file_exists("./$filename")) shell_exec("./get-file $file_id \"$filename\"");

if (file_exists($filename)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($filename));
    readfile($filename);
    unlink($filename);
    exit;
}

This works okay. But is there some way to "pipe" the file while it's being downloaded? Let's say the file is 500MB, instead of waiting for the file to download in the server, and then serve it to the client, is there some way to send the content as it's being downloaded? The reason is obvious; I want to minimize the total time it takes for the whole process to complete. If what I ask is possible, it could bring total time to half. Thank you.

Edit: I found this but the solution is based on curl. In my case, the file is being downloaded by external script. So I want to run a loop in which the PHP script checks if new bytes are written in the file, and proceed to sending them to the client, without closing the connection. Note that the file is not text-based, it's an audio file.

Edit: Now I'm closer: I modified the external script to output the file in stdout, effectively feeding its data to shell_exec. Now, how can I send data before shell_exec has finished? I guess I'll have to use something like ob_flush() but some help would be appreciated. Thanks again

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="' . basename($filename) . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
// This sends the data AFTER the exec finishes. I want to send them as they arrive, real-time
echo shell_exec("get-file $file_id");
die();
  • Welcome, to improve your experience on SO please [take the tour](http://stackoverflow.com/tour) and read [how to ask](https://stackoverflow.com/help/how-to-ask), an [On Topic question](https://stackoverflow.com/help/on-topic), then look at the [Question Check list](https://meta.stackoverflow.com/questions/260648/stack-overflow-question-checklist), the [perfect question](http://codeblog.jonskeet.uk/2010/08/29/writing-the-perfect-question/) and how to create a [Minimal, Complete and Verifiable Example](http://stackoverflow.com/help/mcve) – RiggsFolly Aug 29 '21 at 11:58
  • Please provide enough code so others can better understand or reproduce the problem. – Community Sep 01 '21 at 06:20

1 Answers1

0

OK I found the answer in other posts.

I just use passthru() instead of shell_exec() and it seems to be working great.

Thank everybody! <3