Reputation: 221
Good afternoon,
I try to display an image from AWS S3 storage. I use the gaufrette file configuration which works when I upload file in AWS S3 storage.
Gaufrette configuration:
knp_gaufrette:
adapters:
images:
aws_s3:
service_id: "infra.aws_s3.client"
bucket_name: "%amazon_s3.bucket_name%"
detect_content_type: true
options:
directory: "%amazon_s3.directories.images%"
acl: public-read
documents:
aws_s3:
service_id: "infra.aws_s3.client"
bucket_name: "%amazon_s3.bucket_name%"
detect_content_type: true
options:
directory: "%amazon_s3.directories.documents%"
acl: public-read
imports:
aws_s3:
service_id: "infra.aws_s3.client"
bucket_name: "%amazon_s3.bucket_name%"
detect_content_type: true
options:
directory: "%amazon_s3.directories.imports%"
acl: public-read
filesystems:
images:
adapter: images
alias: images_filesystem
documents:
adapter: documents
alias: documents_filesystem
imports:
adapter: imports
alias: imports_filesystem
Controller code:
<?php
namespace App\Application\Controller;
use App\Application\Controller\Rest\RestController;
use App\Domain\Entity\BuildingMedia;
use App\Domain\Entity\PropertyPicture;
use App\Infrastructure\Command\Command\CommandBus;
use App\Infrastructure\Repository\BuildingMediaRepository;
use App\Infrastructure\Repository\PropertyPictureRepository;
use Gaufrette\Filesystem;
use Gaufrette\StreamWrapper;
use JMS\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Swagger\Annotations as SWG;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
class MediaController extends RestController
{
/**
* @var PropertyPictureRepository
*/
private $propertyPictureRepository;
/**
* @var BuildingMediaRepository
*/
private $buildingMediaRepository;
/**
* @var Filesystem
*/
private $awsS3;
/**
* MediaController constructor.
*
* @param PropertyPictureRepository $propertyPictureRepository
* @param BuildingMediaRepository $buildingMediaRepository
* @param Filesystem $awsS3
* @param SerializerInterface $serializer
* @param CommandBus $commandBus
*/
public function __construct(
PropertyPictureRepository $propertyPictureRepository,
BuildingMediaRepository $buildingMediaRepository,
Filesystem $awsS3,
SerializerInterface $serializer,
CommandBus $commandBus
) {
$this->propertyPictureRepository = $propertyPictureRepository;
$this->buildingMediaRepository = $buildingMediaRepository;
$this->awsS3 = $awsS3;
parent::__construct($serializer, $commandBus);
}
/**
* @Operation(
* tags={"Media"},
* summary="Read a property's picture.",
* @SWG\Response(
* response="200",
* description="OK"
* ),
* @SWG\Response(
* response="400",
* description="Bad request"
* ),
* @SWG\Response(
* response="401",
* description="Unauthorized"
* ),
* @SWG\Response(
* response="403",
* description="Access denied"
* ),
* @SWG\Response(
* response="404",
* description="Entity not found"
* ),
* @SWG\Response(
* response="500",
* description="Internal server error"
* )
* )
*
* @ParamConverter("propertyPicture", converter="property_picture")
*
* @param PropertyPicture $propertyPicture
*
* @return BinaryFileResponse
*/
public function propertyPictureReadAction(PropertyPicture $propertyPicture): BinaryFileResponse
{
$adapter = $this->awsS3->getAdapter();
$filePath = $adapter->read(
'group'.DIRECTORY_SEPARATOR.
$this->getUser()->getGroupId().DIRECTORY_SEPARATOR.
'property'.DIRECTORY_SEPARATOR.
$propertyPicture->getProperty()->getIdValue().DIRECTORY_SEPARATOR.
$propertyPicture->getFilename()
);
$response = new BinaryFileResponse($filepath);
$response->headers->set('Content-Type', 'image/jpeg');
$response->setContentDisposition(
ResponseHeaderBag::DISPOSITION_INLINE,
$propertyPicture->getFilename()
);
return $response;
}
}
If I try to use getLink()
from $propertyPicture
(the method returns the file URL save in database), BinaryFileResponse
not found the file from given URL.
I need to have the file URL from Gaufrette to display the file in API response.
Upvotes: 1
Views: 1141
Reputation: 221
After try many possible solution, I have find this one for pictures (and it is working perfecly, even if you use a private bucket in AWS S3):
<?php
namespace App\Application\Controller;
use App\Application\Controller\Rest\RestController;
use App\Domain\Entity\BuildingMedia;
use App\Domain\Entity\PropertyPicture;
use App\Infrastructure\Command\Command\CommandBus;
use App\Infrastructure\Repository\BuildingMediaRepository;
use App\Infrastructure\Repository\PropertyPictureRepository;
use Gaufrette\Filesystem;
use JMS\Serializer\SerializerInterface;
use Symfony\Component\HttpFoundation\Response;
use Swagger\Annotations as SWG;
use Nelmio\ApiDocBundle\Annotation\Operation;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
use Symfony\Component\HttpKernel\Exception\HttpException;
class MediaController extends RestController
{
/**
* @var PropertyPictureRepository
*/
private $propertyPictureRepository;
/**
* @var BuildingMediaRepository
*/
private $buildingMediaRepository;
/**
* @var Filesystem
*/
private $awsS3;
/**
* MediaController constructor.
*
* @param PropertyPictureRepository $propertyPictureRepository
* @param BuildingMediaRepository $buildingMediaRepository
* @param Filesystem $awsS3
* @param SerializerInterface $serializer
* @param CommandBus $commandBus
*/
public function __construct(
PropertyPictureRepository $propertyPictureRepository,
BuildingMediaRepository $buildingMediaRepository,
Filesystem $awsS3,
SerializerInterface $serializer,
CommandBus $commandBus
) {
$this->propertyPictureRepository = $propertyPictureRepository;
$this->buildingMediaRepository = $buildingMediaRepository;
$this->awsS3 = $awsS3;
parent::__construct($serializer, $commandBus);
}
/**
* @Operation(
* tags={"Media"},
* summary="Read a property's picture.",
* @SWG\Response(
* response="200",
* description="OK"
* ),
* @SWG\Response(
* response="400",
* description="Bad request"
* ),
* @SWG\Response(
* response="401",
* description="Unauthorized"
* ),
* @SWG\Response(
* response="403",
* description="Access denied"
* ),
* @SWG\Response(
* response="404",
* description="Entity not found"
* ),
* @SWG\Response(
* response="500",
* description="Internal server error"
* )
* )
*
* @ParamConverter("propertyPicture", converter="property_picture")
*
* @param PropertyPicture $propertyPicture
*
* @return Response
*/
public function propertyPictureReadAction(PropertyPicture $propertyPicture): Response
{
$adapter = $this->awsS3->getAdapter();
$content = $adapter->read(
'group'.DIRECTORY_SEPARATOR.
$this->getUser()->getGroupId().DIRECTORY_SEPARATOR.
'property'.DIRECTORY_SEPARATOR.
$propertyPicture->getProperty()->getIdValue().DIRECTORY_SEPARATOR.
$propertyPicture->getFilename()
);
return new Response($content, 200, array(
'Content-Type' => 'image/jpeg'
));
}
}
The read()
method from Gaufrette
returns the file content, not the real path. So, I have just change the returns value from BinaryFileResponse
to Response
and set manually the Content-Type
.
The next upgrade, if you have the same processing is to set the type MIME in database when file is save and returns it when you need to display it like with a similar route from your API.
Upvotes: 0