Aşağıdaki örnek ile JPG, GIF and PNG resim yükleme, thumbnail yaratma, kenarları doldurma ve ortalama işlemi yapabiliriz.


Upload klasör yapısı


İsterseniz "app" yerine "web" klasörünü kullanabilirsiniz. Yapıda içi boş olan .gitkeep dosyası olmak zorunda.


app
upload
image
thumbnail
.gitkeep

Dosya .gitignore'nin içeriği


Bu satırlar git komutlarının yüklenen resimleri önemsememesini sağlar ve resimler remote repositorye gönderilmez.


/app/upload/image/*.*
/app/upload/image/thumbnail/*.*
!app/upload/image/thumbnail/.gitkeep

İzinleri ayarlama


# MAC OS
Inanzzz-MacBook-Pro:sport inanzzz$ HTTPDUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1`
Inanzzz-MacBook-Pro:sport inanzzz$ sudo chmod -R +a "$HTTPDUSER allow delete,write,append,file_inherit,directory_inherit" app/upload
Inanzzz-MacBook-Pro:sport inanzzz$ sudo chmod -R +a "`whoami` allow delete,write,append,file_inherit,directory_inherit" app/upload

# UBUNTU version.1
Inanzzz-MacBook-Pro:sport inanzzz$ HTTPDUSER=`ps aux | grep -E '[a]pache|[h]ttpd|[_]www|[w]ww-data|[n]ginx' | grep -v root | head -1 | cut -d\ -f1`
Inanzzz-MacBook-Pro:sport inanzzz$ sudo setfacl -R -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/upload
Inanzzz-MacBook-Pro:sport inanzzz$ sudo setfacl -dR -m u:"$HTTPDUSER":rwX -m u:`whoami`:rwX app/upload

# UBUNTU version.2
Inanzzz-MacBook-Pro:sport inanzzz$ chmod -R 755 app/upload
Inanzzz-MacBook-Pro:sport inanzzz$ chown -R www-data:www-data app/upload

GD kütüphanesini yükleme


Bu kütüphanenin yüklü olduğunu varsyıyorum ama yüklü değilse, Google'dan arama yapıp yükleyebilirsiniz. Ubuntu kullanıcıları pek sorun yaşamazlar ama Mac OS kullanıcıları PNG desteği problemi yaşayabilirler. Eğer sorun olursa aşağıdaki işlem ile çözüme ulaşabilirsiniz.


PNG desteklenmiyor - phpinfo()



Inanzzz-MacBook-Pro:~ inanzzz$ curl -s http://php-osx.liip.ch/install.sh | bash -s 5.6
......
......
......
Restarting Apache
Syntax OK
Inanzzz-MacBook-Pro:~ inanzzz$ export PATH=/usr/local/php5/bin:$PATH
Inanzzz-MacBook-Pro:~ inanzzz$ sudo apachectl graceful

PNG artık destekleniyor - phpinfo()



Parameters YML


parameters:
image_upload:
image_upload_dir: /upload/image/
thumbnail_upload_dir: /upload/image/thumbnail/
valid_extensions:
- jpg
- jpeg
- gif
- png
thumbnail_defaults:
height: 200
width: 200
red: 200
green: 0
blue: 0

Services YML


services:
football_frontend.service.image_upload:
class: Football\FrontendBundle\Service\ImageUploadService
arguments: [%kernel.root_dir%, %image_upload%]

ImageUploadService class


Bu sadece size genel bir fikir veriyor ama iyileşteribilirsiniz.


namespace Football\FrontendBundle\Service;

/**
* Uploads image and creates thumbnail. Image does not get distorted when resized.
*
* Use:
* $thumbnail = array('thumbnail' => true, 'padding' => true);
* $this->get('image_uploader')->upload($submission->getFlag(), $thumbnail);
*/
class ImageUploadService
{
private $imageUploadDir;
private $thumbnailUploadDir;
private $thumbnailDefaults;
private $validExtensions;

/**
* @param $root
* @param $imageUpload
*/
public function __construct($root, $imageUpload)
{
$this->imageUploadDir = $root . $imageUpload['image_upload_dir'];
$this->thumbnailUploadDir = $root . $imageUpload['thumbnail_upload_dir'];
$this->thumbnailDefaults = $imageUpload['thumbnail_defaults'];
$this->validExtensions = $imageUpload['valid_extensions'];
}

/**
* Image gets uploaded.
*
* @param $image
* @param array $thumbnail
* @return array|string
*/
public function upload($image, array $thumbnail = null)
{
$extension = $image->guessExtension();

if (! in_array($extension, $this->validExtensions)) {
return 'Invalid image format.';
}

$originalName = strip_tags($image->getClientOriginalName());
$newName = sha1(crc32(time()) . microtime() . $originalName) . '.' . $extension;

$image->move($this->imageUploadDir, $newName);

if (! file_exists($this->imageUploadDir . $newName)) {
return 'Image could not be uploaded.';
}

if (! is_null($thumbnail) && count($thumbnail) == 2) {
if ($thumbnail['thumbnail'] === true) {
if ($thumbnail['padding'] === true) {
$this->createThumbnailWithPadding(
$this->imageUploadDir . $newName,
$this->thumbnailUploadDir . $newName
);
} else {
$this->createThumbnailWithoutPadding(
$this->imageUploadDir . $newName,
$this->thumbnailUploadDir . $newName
);
}
}
}

return array('originalName' => $originalName, 'newName' => $newName);
}

/**
* Resizes image with adding padding to the shortest edge and centers the image.
* Transparency of image is destroyed.
*
* @param $sourceImage
* @param $targetImage
* @return bool
*/
private function createThumbnailWithPadding($sourceImage, $targetImage)
{
list($sourceWidth, $sourceHeight, $sourceType) = getimagesize($sourceImage);

$sourceGdImage = imagecreatefromstring(file_get_contents($sourceImage));

//Determine scale based on the longest edge
if ($sourceHeight > $sourceWidth) {
$scale = ($this->thumbnailDefaults['height'] / $sourceHeight);
} else {
$scale = ($this->thumbnailDefaults['width'] / $sourceWidth);
}

//Calculate new image dimensions
$thumbnailWidth = ($sourceWidth * $scale);
$thumbnailHeight = ($sourceHeight * $scale);

//Determine offset coordinates so that new image is centered
$offsetX = (($this->thumbnailDefaults['width'] - $thumbnailWidth) / 2);
$offsetY = (($this->thumbnailDefaults['height'] - $thumbnailHeight) / 2);

//Create new image and fill with background colour
$thumbnailGdImage = imagecreatetruecolor($this->thumbnailDefaults['width'], $this->thumbnailDefaults['height']);

//Set background colour
$bgColor = imagecolorallocate(
$thumbnailGdImage,
$this->thumbnailDefaults['red'],
$this->thumbnailDefaults['green'],
$this->thumbnailDefaults['blue']
);

//Fill background colour
imagefill($thumbnailGdImage, 0, 0, $bgColor);
//Copy and resize original image into center of new image
imagecopyresampled(
$thumbnailGdImage,
$sourceGdImage,
$offsetX,
$offsetY,
0,
0,
$thumbnailWidth,
$thumbnailHeight,
$sourceWidth,
$sourceHeight
);

//clearstatcache();

switch ($sourceType) {
case IMAGETYPE_GIF:
imagegif($thumbnailGdImage, $targetImage, 90);
break;
case IMAGETYPE_JPEG:
imagejpeg($thumbnailGdImage, $targetImage, 90);
break;
case IMAGETYPE_PNG:
imagepng($thumbnailGdImage, $targetImage, 9);
break;
}

imagedestroy($sourceGdImage);
imagedestroy($thumbnailGdImage);

return true;
}

/**
* Resizes image without adding padding to short edge.
* Transparency of image is preserved.
*
* @param $sourceImage
* @param $targetImage
* @return bool
*/
private function createThumbnailWithoutPadding($sourceImage, $targetImage)
{
list($sourceWidth, $sourceHeight, $sourceType) = getimagesize($sourceImage);

switch ($sourceType) {
case IMAGETYPE_GIF:
$sourceGdImage = imagecreatefromgif($sourceImage);
break;
case IMAGETYPE_JPEG:
$sourceGdImage = imagecreatefromjpeg($sourceImage);
break;
case IMAGETYPE_PNG:
$sourceGdImage = imagecreatefrompng($sourceImage);
break;
}

if ($sourceGdImage === false) {
return false;
}

$sourceAspectRatio = ($sourceWidth / $sourceHeight);
$thumbnailAspectRatio = ($this->thumbnailDefaults['width'] / $this->thumbnailDefaults['height']);

if ($sourceWidth <= $this->thumbnailDefaults['width'] && $sourceHeight <= $this->thumbnailDefaults['height']) {
$thumbnailWidth = $sourceWidth;
$thumbnailHeight = $sourceHeight;
} elseif ($thumbnailAspectRatio > $sourceAspectRatio) {
$thumbnailWidth = (int) ($this->thumbnailDefaults['height'] * $sourceAspectRatio);
$thumbnailHeight = $this->thumbnailDefaults['height'];
} else {
$thumbnailWidth = $this->thumbnailDefaults['width'];
$thumbnailHeight = (int) ($this->thumbnailDefaults['width'] / $sourceAspectRatio);
}

$thumbnailGdImage = imagecreatetruecolor($thumbnailWidth, $thumbnailHeight);

//Keep the transparency
imagecolortransparent($thumbnailGdImage, imagecolorallocatealpha($thumbnailGdImage, 0, 0, 0, 127));
imagealphablending($thumbnailGdImage, false);
imagesavealpha($thumbnailGdImage, true);

imagecopyresampled(
$thumbnailGdImage,
$sourceGdImage,
0,
0,
0,
0,
$thumbnailWidth,
$thumbnailHeight,
$sourceWidth,
$sourceHeight
);

//clearstatcache();

switch ($sourceType) {
case IMAGETYPE_GIF:
imagegif($thumbnailGdImage, $targetImage, 90);
break;
case IMAGETYPE_JPEG:
imagejpeg($thumbnailGdImage, $targetImage, 90);
break;
case IMAGETYPE_PNG:
imagepng($thumbnailGdImage, $targetImage, 9);
break;
}

imagedestroy($sourceGdImage);
imagedestroy($thumbnailGdImage);

return true;
}
}

Controller


class CountryController
{
const ROUTER_PREFIX = 'football_frontend_country_';

public function createProcessAction(Request $request)
{
if ($request->getMethod() != 'POST') {
throw new Exception('Country create: only POST method is allowed.');
}

$form = $this->getForm(
new Country(),
'POST',
$this->generateUrl(self::ROUTER_PREFIX . 'create')
);
$form->handleRequest($request);

if (!$form->isSubmitted()) {
throw new Exception('Country create: form is not submitted.');
}

if ($form->isValid() !== true) {
return $this->getFormView(
'create',
[
'form' => $form->createView()
]
);
}

try {
$data = $form->getData();

$thumbnail = array('thumbnail' => true, 'padding' => false);
$upload = $this->get('football_frontend.service.image_upload')->upload($data->getFlag(), $thumbnail);

if (! is_array($upload)) {
exit('Do something with failure.');
}

echo '<pre>';
print_r($upload);
exit;

// Do something with result
} catch (Exception $e) {
throw new Exception(sprintf('Exception [%s]: %s', $e->getCode(), $e->getMessage()));
}
}
}

FormType


namespace Football\FrontendBundle\Form\Type;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolverInterface;
use Symfony\Component\Validator\Constraints\File;
use Symfony\Component\Validator\Constraints\NotBlank;

class CountryType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options = [])
{
$builder
->setMethod($options['method'])
->setAction($options['action'])
->add(
'flag',
'file',
[
'error_bubbling' => true,
'constraints' => [
new NotBlank(
[
'message' => 'Flag is required.'
]
),
new File(
[
'maxSize' => '1000000', // 1MB
'mimeTypes' => ['image/png','image/jpeg','image/jpg','image/gif'],
'uploadErrorMessage' => 'Flag file could not be uploaded for some unknown reason.'
]
)
]
]
);
}

public function getName()
{
return 'country';
}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{
$resolver->setDefaults(
['data_class' => 'Football\FrontendBundle\Entity\Country']
);
}
}

Sonuç


Array
(
[originalName] => house.png
[newName] => 66db00a41de42a1658b0d9d9bf5e400c2e57b144.png
)