从Slim Framework下载文件时出现问题

I want to download file through Slim Framework (The reason why I'm using Slim Framework is because I want to write a simple REST API). I found this post: Download file from Slim Framework 2.4 and this post: http://help.slimframework.com/discussions/questions/359-file-download. I followed the method. Here is my code:

$app->get('/download/:id', 'authenticate', function($id) use ($app)
{    
    $log = '../download/'.$id.'/myfile.zip';

    $res = $app->response()->headers();
    $res['Content-Description'] = 'File Transfer';
    $res['Content-Type'] = 'application/octet-stream';
    $res['Content-Disposition'] ='attachment; filename=' . basename($log);
    $res['Content-Transfer-Encoding'] = 'binary';
    $res['Expires'] = '0';
    $res['Cache-Control'] = 'must-revalidate';
    $res['Pragma'] = 'public';
    $res['Content-Length'] = filesize($log);

    readfile($log);    

    // NOTE: 
//        $response = array();
//        $response["error"] = false;
//        echoRespnse(200, $response);

});

I'm using the Google Chrome's Advanced Rest Client application to test. The problem is the browser hung after the file downloaded.If I comments out the NOTE part in my source code, the browser won't hang again. But I got a "Unexpected token P" error.

Can anybody help? Thanks.

Try the solution here: PHP readfile() adding extra bytes to downloaded file.

You lack the calls to ob_clean, flush and exit.

The problem might be becasue of extra characters output with the rest of the file contents.

Is the solution above working for you? Here's my code, which just outputs obscure characters directly into the browser window:

$app->get('/file/:fileid', function($fileid) use ($app)
{
    $zip = new ZipArchive();
    $zipname = "zipfile3.zip"; // Zip name
    $zip->open($zipname,  ZipArchive::CREATE);
    $files = array ( "sprecher_inserts_en_VB.doc" );

    foreach ($files as $file) {
        $path = "uploads/".$file;
        if(file_exists($path)){
            $zip->addFromString(basename($path),  file_get_contents($path));  
        }
        else{
            echo"file does not exist";
        }
    }
    $zip->close();
    // after that, the zip file is on the server and valid when downloaded manually (e.g. by entering its URL directly)

    $res = $app->response()->headers();
    $res['Content-Description'] = 'File Transfer';
    $res['Content-Type'] = 'application/octet-stream';
    $res['Content-Disposition'] ='attachment; filename=' . basename($zipname);
    $res['Content-Transfer-Encoding'] = 'binary';
    $res['Expires'] = '0';
    $res['Cache-Control'] = 'must-revalidate';
    $res['Pragma'] = 'public';
    $res['Content-Length'] = filesize($zipname);

    ob_clean();    
    flush();
    readfile($zipname);    
    exit();
});

The output in the browser window is the following, no dialog for downloading the file is loaded whatsoever: Output of the code shown above

maybe it's a little late but you can use this package for slim http file response : https://github.com/mhndev/slim-file-response

For Slim 3, I had a bit of struggle. I struggled with this in Slim 3.0. I was trying something like the following and the pdf binary was getting displayed on the screen.

$header['Content-Description']  = 'File Transfer';
$header['Content-Disposition'] = 'attachment; filename="' .basename("$file") . '"';

// ...
$response   = $response->withHeader($header);

In order to make it work, you need to set the key/value pairs using $response->withHeader(). And it works like a charm. For example:

$response   = $response->withHeader('Content-Type', 'application/pdf');
$response   = $response->withHeader('Content-Description', 'File Transfer');
$response   = $response->withHeader('Content-Disposition', 'attachment; filename="' .basename("$file") . '"');
$response   = $response->withHeader('Content-Transfer-Encoding', 'binary');
$response   = $response->withHeader('Expires', '0');
$response   = $response->withHeader('Cache-Control', 'must-revalidate');
$response   = $response->withHeader('Pragma', 'public');
$response   = $response->withHeader('Content-Length', filesize($file));