Last active
August 4, 2016 21:07
-
-
Save simshaun/3ef497b7c092b1093634470cc37113f6 to your computer and use it in GitHub Desktop.
Makes use of Flysystem for fs abstraction and is setup in a manner that lets me easily swap out local files (single-server apps) with remote files (e.g. S3, for multi-server apps) by tweaking the service definitions. The Avatar file is just an example of how I might handle an image. Validation is enforced before this handler is called.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\File; | |
use AppBundle\File\Namer\NamerInterface; | |
use AppBundle\File\UrlGenerator\FileUrlGeneratorInterface; | |
use League\Flysystem\Filesystem; | |
abstract class AbstractFile | |
{ | |
/** @var Filesystem */ | |
protected $filesystem; | |
/** @var NamerInterface */ | |
protected $namer; | |
/** @var FileUrlGeneratorInterface */ | |
protected $urlGenerator; | |
public function setFilesystem(Filesystem $filesystem) | |
{ | |
$this->filesystem = $filesystem; | |
} | |
public function setNamer(NamerInterface $namer) | |
{ | |
$this->namer = $namer; | |
} | |
public function setUrlGenerator(FileUrlGeneratorInterface $urlGenerator) | |
{ | |
$this->urlGenerator = $urlGenerator; | |
} | |
public function getPublicUrl($filename) | |
{ | |
return $this->urlGenerator->generate($this->getBasePath().$filename); | |
} | |
public function getPublicUrlBase() | |
{ | |
return $this->urlGenerator->generate($this->getBasePath()); | |
} | |
protected function getBasePath() | |
{ | |
return; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\File\Namer; | |
use Symfony\Component\HttpFoundation\File\UploadedFile; | |
interface NamerInterface | |
{ | |
public function getName(UploadedFile $file); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\File\Namer; | |
use RandomLib; | |
use Symfony\Component\HttpFoundation\File\UploadedFile; | |
/** | |
* This namer keeps the original filename but appends a random string to the end. | |
*/ | |
class OriginalRandomNamer implements NamerInterface | |
{ | |
private $opts = [ | |
'length' => 6, | |
]; | |
/** | |
* @param int $length of random portion of filename | |
*/ | |
public function setLength($length) | |
{ | |
$this->opts['length'] = (int) $length; | |
} | |
public function getName(UploadedFile $file) | |
{ | |
$factory = new RandomLib\Factory(); | |
$generator = $factory->getMediumStrengthGenerator(); | |
return sprintf( | |
'%s_%s.%s', | |
pathinfo($file->getClientOriginalName(), PATHINFO_FILENAME), | |
$generator->generateString($this->opts['length'], RandomLib\Generator::CHAR_ALNUM), | |
$file->getClientOriginalExtension() | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\File\Namer; | |
use RandomLib; | |
use Symfony\Component\HttpFoundation\File\UploadedFile; | |
/** | |
* This namer generates a random filename. | |
*/ | |
class RandomNamer implements NamerInterface | |
{ | |
private $opts = [ | |
'length' => 6, | |
]; | |
/** | |
* @param int $length of random portion of filename | |
*/ | |
public function setLength($length) | |
{ | |
$this->opts['length'] = (int) $length; | |
} | |
public function getName(UploadedFile $file) | |
{ | |
$factory = new RandomLib\Factory(); | |
$generator = $factory->getMediumStrengthGenerator(); | |
return sprintf( | |
'%s.%s', | |
$generator->generateString($this->opts['length'], RandomLib\Generator::CHAR_ALNUM), | |
$file->getClientOriginalExtension() | |
); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\File\UrlGenerator; | |
interface FileUrlGeneratorInterface | |
{ | |
public function generate($path); | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\File\UrlGenerator; | |
use Symfony\Component\Routing\Generator\UrlGeneratorInterface; | |
class Local implements FileUrlGeneratorInterface | |
{ | |
private $router; | |
public function __construct(UrlGeneratorInterface $router) | |
{ | |
$this->router = $router; | |
} | |
public function generate($path) | |
{ | |
return $this->router->generate('app_file', ['path' => $path]); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
namespace AppBundle\File\User; | |
use AppBundle\Entity\User; | |
use AppBundle\File\AbstractFile; | |
use Intervention\Image\Constraint; | |
use Intervention\Image\ImageManager; | |
use Symfony\Component\HttpFoundation\File\Exception\FileException; | |
use Symfony\Component\HttpFoundation\File\UploadedFile; | |
class AvatarFile extends AbstractFile | |
{ | |
private $imageManager; | |
public function __construct(ImageManager $imageManager) | |
{ | |
$this->imageManager = $imageManager; | |
} | |
protected function getBasePath() | |
{ | |
return 'user/avatar/'; | |
} | |
public function upload(User $user) | |
{ | |
$file = $user->getAvatarFile(); | |
if (!$file instanceof UploadedFile) { | |
return; | |
} | |
if (!$file->isValid()) { | |
throw new FileException($file->getErrorMessage()); | |
} | |
$name = $user->getId().'-'.$this->namer->getName($file); | |
$image = $this->imageManager->make($file->openFile()); | |
$extension = strtolower($file->getExtension()); | |
$resizeConstraint = function (Constraint $constraint) { | |
$constraint->aspectRatio(); | |
$constraint->upsize(); | |
}; | |
$image->backup(); | |
$image->fit(400, 400, $resizeConstraint); | |
$this->filesystem->write($this->getBasePath().'400/'.$name, $image->encode($extension, 85)); | |
$image->reset(); | |
$image->fit(50, 50, $resizeConstraint); | |
$this->filesystem->write($this->getBasePath().'50/'.$name, $image->encode($extension, 85)); | |
$image->reset(); | |
return $name; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# | |
# Example file service | |
# | |
file.user.avatar: | |
class: AppBundle\File\User\AvatarFile | |
parent: file.abstract | |
arguments: ['@intervention.image_manager'] | |
calls: | |
- [setNamer, ['@file.namer.random']] | |
# | |
# Files | |
# | |
file.abstract: | |
class: AppBundle\File\AbstractFile | |
abstract: true; | |
calls: | |
- [setFilesystem, ['@file.system.default']] | |
- [setNamer, ['@file.namer.default']] | |
- [setUrlGenerator, ['@file.url_generator.default']] | |
file.system.default: | |
alias: file.system.local | |
file.url_generator.default: | |
alias: file.url_generator.local | |
file.namer.default: | |
alias: file.namer.original_random | |
file.namer.random: | |
class: AppBundle\File\Namer\RandomNamer | |
file.namer.original_random: | |
class: AppBundle\File\Namer\OriginalRandomNamer | |
# Local | |
file.system.local: | |
class: League\Flysystem\Filesystem | |
arguments: ['@file.system_adapter.local'] | |
file.url_generator.local: | |
class: AppBundle\File\UrlGenerator\Local | |
arguments: ['@router'] | |
file.system_adapter.local: | |
class: League\Flysystem\Adapter\Local | |
arguments: ['%upload_path%'] |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
app_file: | |
path: "%upload_folder%/{path}" | |
requirements: | |
path: .* |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment