Slim 3 Download Files

The data needs to written to the body of the response object. You can use the built-in Slim Stream class together with fopen to to this for you:

    $app->get('/test-download', function($request, Slim\Http\Response $response, $args) {
        $file = __DIR__ . '/test.html';
        $fh = fopen($file, 'rb');

        $stream = new \Slim\Http\Stream($fh); // create a stream instance for the response body

        return $response->withHeader('Content-Type', 'application/force-download')
                        ->withHeader('Content-Type', 'application/octet-stream')
                        ->withHeader('Content-Type', 'application/download')
                        ->withHeader('Content-Description', 'File Transfer')
                        ->withHeader('Content-Transfer-Encoding', 'binary')
                        ->withHeader('Content-Disposition', 'attachment; filename="' . basename($file) . '"')
                        ->withHeader('Expires', '0')
                        ->withHeader('Cache-Control', 'must-revalidate, post-check=0, pre-check=0')
                        ->withHeader('Pragma', 'public')
                        ->withBody($stream); // all stream contents will be sent to the response
    });

The Content-Length header will be automatically appended.

The code also worked for me with one Content-Type header, and without the Content-Transfer-Encoding header. So you may be able to simplify this by leaving headers out.

1 Like