Slim 框架 - 创建一个路由 return 一个可下载的文件流

Slim framework -creating a route which will return a downloadable file stream

我在 index.php

中创建了以下 Slim Framework 路由

$app->get('/generatecsv', ShippingCSVGenerator::class . ':generateShippingCSV');

函数 generateShippingCSV() 被正确调用,但是我想要 return 一个流,它应该可以通过 JS 在任何可能需要的视图中下载。

public function generateShippingCSV()
{
    // ...some code here... //
    $out = fopen('dispatch.csv', 'w');
    foreach ($CSVArray as $fields) {
        fputcsv($out, $fields);
    }
    $stream = new \GuzzleHttp\Psr7\LazyOpenStream('dispatch.csv', 'r');
    $response->withBody($stream);
    return $response;
}

上面的函数正确地创建了 CSV,但是我不想创建文件 - 我想 return 文件流。

* 编辑 *

添加:

return $response->withHeader('Content-Type', 'application/force-download')
    ->withBody($stream);

...使文件在通过浏览器访问路由时可用,但我更愿意 return 流,而不是生成和 return 物理文件。

有很多方法可以做到这一点。例如:

  1. 加长修身 Slim\Http\RequestBody class

    <?php
    
    use Slim\Http\RequestBody;
    
    class CsvRequestBody extends RequestBody
    {
         public writeCsv(array $CSVArray) 
         {
              $this->rewind();
              foreach ($CSVArray as $fields) {
                  fputcsv($this->stream, $fields);
              }      
         } 
    }
    

    然后在你的代码中输出响应

    $csvBody = new CsvRequestBody();
    $scvBody->writeCsv($CSVArray);
    return $response->withHeader('Content-Type', 'application/force-download')
                    ->withBody($csvBody);
    
  2. 将数据写入php://temp,将其读取到一个变量,然后将其写入响应主体。

    $out = fopen('php://temp', 'w');
    foreach ($CSVArray as $fields) {
        fputcsv($out, $fields);
    }
    rewind($out);
    $csvData = stream_get_contents($out);
    fclose($out);
    
    $response->getBody()->rewind();
    $response->getBody()->write($csvData);
    return $response->withHeader('Content-Type', 'application/force-download');