How to return files? (solved)

Hello,

Using Slim 4, PHP 7.3, how can I return (respond) files ?

In the action, I generate a PNG file, that I store on the disk, and I need to return the file ou redirect to an error page if there is an error.

Th.

I wrote a tiny blog post for Slim 3. The principle is still the same. You just have to use your specific PSR-7 Stream object instead.

PS: Here is a new article for Slim 4:

Hello.

I’m lost.

I’ve tried:

private $streamFactory;
public function __construct(StreamFactoryInterface $streamFactory) {
  $this->streamFactory = $streamFactory;
}
...
$stream = $this->streamFactory->createStreamFromFile($pngFilePath);
return $response->withBody($stream);

But I get this error:

Entry "Psr\Http\Message\StreamFactoryInterface" cannot be resolved: the class is not instantiable

I’ve also tried:

use Psr\Http\Message\StreamInterface as Stream;
$stream = fopen($pngFilePath, 'r');
return $response->withBody(new Stream($stream));

Error:

Cannot instantiate interface Psr\Http\Message\StreamInterface

It should work if you add a container definiton like this:

use Psr\Container\ContainerInterface;
use Psr\Http\Message\StreamFactoryInterface;
// ...

StreamFactoryInterface::class => function (ContainerInterface $container) {
    return new \Slim\Psr7\Factory\StreamFactory();
},
1 Like

Yes it works. Thanks…

My code, if it helps someone else in the future:

boot.php:

$containerBuilder = new ContainerBuilder();
$containerBuilder->addDefinitions(__DIR__ . '/../config/container.php');

container.php:

use Psr\Http\Message\StreamFactoryInterface;
use Slim\Psr7\Factory\StreamFactory;
return [
  StreamFactoryInterface::class => function (Container $container) {
    return new StreamFactory();
  },
  ...

The controller creates an SVG file from a template (with variables), then generates the PNG file with Inkscape, then send the file.

My controller:

class GraphController {
  private $streamFactory;

  public function __construct(StreamFactoryInterface $streamFactory) {
    $this->streamFactory = $streamFactory;
  }

  public getGraph() {

    $pngFile = 'somepath/foo.png';
    $svgFile = 'somepath/foo.svg';

    ob_start();
    include($graphs_dir . 'some-svg-template.php');
    $include_svg = ob_get_contents();
    ob_end_clean();
    
// DO NOT INDENT
$svg = <<< "SVG"
{$include_svg}
SVG;

    $fichierSVG = fopen($svgFile, 'w+');
    fputs($fichierSVG, '<?xml version="1.0" encoding="UTF-8" standalone="no"?>');
    fputs($fichierSVG, "\n");
    fputs($fichierSVG, $svg);
    fclose($fichierSVG); 

    exec("inkscape --file=$svgFile --export-png=$pngFile --export-width=$size --export-height=$size", $out);

    $stream = $this->streamFactory->createStreamFromFile($pngFile);

    return $response
        ->withHeader('Content-Type', 'image/png')
        ->withBody($stream);