Isaac Bosca Isaac Bosca - 4 months ago 21
PHP Question

How to solve "Unable to create the "%kernel.root_dir%/../web/uploads" directory" error in Symfony2

I'm working with a bundle to upload any type of file.

For this purpose, I created a new bundle uploadBundle with the following files:

Entity "Archivo.php"



<?php

namespace SisEvo\UploadBundle\Entity;


use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Validator\Constraints as Assert;
use Doctrine\ORM\Mapping as ORM;

/**
* @ORM\Entity()
*/
class Archivo {

/**
* @ORM\Id
* @ORM\Column(type="integer")
* @ORM\GeneratedValue(strategy="AUTO")
*/
private $id;

/**
* @ORM\Column(type="integer")
*/
private $idTipo;

/**
* @ORM\Column(type="integer")
*/
private $idAgregado;

/**
* @var File
*
* @Assert\File(
* maxSize = "50M",
* mimeTypes = {"application/pdf", "application/x-pdf, application/x-rar-compressed, application/octet-stream, application/csv, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, application/msword, application/vnd.ms-excel"},
* maxSizeMessage = "El arxiu es massa gran",
* mimeTypesMessage = "El tipus d'arxiu seleccionat no està permitit"
* )
*/
protected $file;


Additionally, this entity contains
get
and
set
required methods, and finally, an upload method that looks like this:

public function upload($file, $path = '%kernel.root_dir%/../web/uploads') {
if (null === $file) {
return;
}
$name = $file->getClientOriginalName();
$file->move(
$path, $name
);
unset($file);
}


Form "ArchivoType.php"



<?php

namespace SisEvo\UploadBundle\Form;

use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Bridge\Doctrine\Form\Type\EntityType;


class ArchivoType extends AbstractType {

/**
* @param FormBuilderInterface $builder
* @param array $options
*/
public function buildForm(FormBuilderInterface $builder, array $options) {
$builder
->add('file', 'file')

;
}

/**
* @param OptionsResolver $resolver
*/
public function configureOptions(OptionsResolver $resolver) {
$resolver->setDefaults(array(
'data_class' => 'SisEvo\UploadBundle\Entity\Archivo'
));
}


}


Controller "UploadController.php"



class UploadController extends Controller {

/**
* @Route("/file_upload/" , name = "file_upload")
*/
public function probarAction() {
$request = $this->getRequest();

$file = new Archivo();
$formulario = $this->createForm(new ArchivoType());

$formulario->handleRequest($request);

if ($formulario->isValid()) {
$em = $this->getDoctrine()->getManager();
$data = $formulario->getData();
$fileUploaded = $data->getFile();
$file->upload($fileUploaded);

echo "SUCCESS!";
}
return $this->render("upload/prova.html.twig"
, array("formulario" => $formulario->createView())
);
}

}


The problem



If the folder
/uploads
doesn't exists, this code works fine; this is, the first time that I use it, but the following times Symfony shows this error:


Unable to create the "%kernel.root_dir%/../web/uploads" directory


And the error is produced in this piece of code in vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/File/File.php at line 110

if (!is_dir($directory)) {
if (false === @mkdir($directory, 0777, true) && !is_dir($directory)) {
throw new FileException(sprintf('Unable to create the "%s" directory', $directory));
}
} elseif (!is_writable($directory)) {
throw new FileException(sprintf('Unable to write in the "%s" directory', $directory));


It's seems like Symfony doesn't find
uploads
folders.
I tried to change permisions with chmod 777 -R, but the issue persists.
Any idea to solve this?
Thanks in advance :)

EDIT with more infomation

First

I am creating a service to upload files from any part of my application, so I created a bundle with an entity and a simple form. The controller post above it's only a proof, and when the
uploadBundle
will been finished, this controller will be deleted and the upload method will be used in each part of the application that I need it.

Furthermore, the code than store the information of each uploaded file in the database are not developed yet.

Answer

The way that you're getting the $path (kernel.root_dir) is wrong

Try this approach:

public function probarAction() {
    $request = $this->getRequest();

    $file = new Archivo();
    $formulario = $this->createForm(new ArchivoType());

    $formulario->handleRequest($request);

    if ($formulario->isValid()) {
        $em = $this->getDoctrine()->getManager();
        $data = $formulario->getData();
        $fileUploaded = $data->getFile();
        $path = $this->get('kernel')->getRootDir() . '/../web/uploads';
        $file->upload($fileUploaded, $path);

        echo "SUCCESS!";
    }
    return $this->render("upload/prova.html.twig"
                , array("formulario" => $formulario->createView())
    );
}

Please let us know if you have some progress

Greetings

Comments