We have moved our forum to GitHub Discussions. For questions about Phalcon v3/v4/v5 you can visit here and for Phalcon v6 here.

Passthru with Phalcon

Hi there,

I'm building an application where users will be able to download files via my server. I need to specify custom headers and use the php fpassthru function so that the file isn't downloaded on the server first. How can I do that in a controller's action method ?

Working pure php code:

<?php

$name = "file.zip";
$url= "https://www.example.com/file.zip";
$filesize = 123455;

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime_type = finfo_file($finfo, $url);

// Send the headers
header("Content-Disposition: attachment; filename=" . $name . ";"); // Remove this to stream in the browser (eg. movie)
header("Content-Type: " . $mime_type);
header("Content-Length: " . $filesize);

// Stream the file
$fp = fopen($url, 'rb');
fpassthru($fp);

exit();

What I've got so far with Phalcon:

<?php

public function downloadFileAction() {
    $name = "file.zip";
    $url= "https://www.example.com/file.zip";
    $filesize = 123455;

    $this->view->disable();
    $response = new \Phalcon\Http\Response();

    $finfo = finfo_open(FILEINFO_MIME_TYPE);
    $mime_type = finfo_file($finfo, $url);

    // Send the headers
    $response->setHeader("Content-Disposition", "attachment; filename=" . $name . ";");
    $response->setContentType($mime_type);
    $response->setHeader("Content-Length", $filesize);

    // Missing passthru

    return $response;
}

I couldn't find anything regarding the fpassthru function in the Phalcon documentation. Any ideas?

Thanks



6.4k
Accepted
answer

$response->setFileToSend($url);

Response::setFileToSend() uses fpassthru and sets some headers too.

edited Feb '18

Hi Òscar,

Thank you for your answer.

I had already tried the Response::setFileToSend() method but the download process wouldn't work. I figured out the file was actually being buffered and it was so big the download would never start for the client.

Here is what eventually worked for me:

<?php

public function downloadAction() {
    $name = "file.zip";
    $url= "https://www.example.com/file.zip";
    $filesize = 123455;

    // Nest the output buffer
    if (ob_get_level()) ob_end_clean();

    // Disable the view
    $this->view->disable();

    // Set headers
    $this->response->setContentType("application/octet-stream");
    $this->response->setHeader("Content-Length", $filesize); 

    $this->response->setFileToSend( $url, $name);

    $this->response->send ();
}