Как решить Невозможно создать ошибку каталога %kernel.root_dir%/../web/uploads в Symfony2

Я работаю с пакетом для загрузки файлов любого типа.
Для этой цели я создал новый пакет uploadBundle со следующими файлами:

Сущность "Архив.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;

Кроме того, этот объект содержит методы get и setrequired и, наконец, метод upload, который выглядит следующим образом:

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

Форма "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'
    ));
}


}

Контроллер "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())
        );
    }

}

Проблема

Если папка /uploads не существует, этот код работает нормально; это первый раз, когда я его использую, но в следующие разы Symfony показывает эту ошибку:

Не удалось создать каталог «%kernel.root_dir%/../web/uploads».

И ошибка возникает в этом фрагменте кода в vendor/symfony/symfony/src/Symfony/Component/HttpFoundation/File/File.php в строке 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));

Кажется, что Symfony не находит uploads папок. Я попытался изменить разрешения с помощью chmod 777 -R, но проблема не устранена. Любая идея решить эту проблему? Заранее спасибо :)

ИЗМЕНИТЬ с дополнительной информацией

Сначала
я создаю службу для загрузки файлов из любой части моего приложения, поэтому я создал пакет с сущностью и простой формой. Сообщение о контроллере выше — это только доказательство, и когда uploadBundle будет завершено, этот контроллер будет удален, а метод загрузки будет использоваться в каждой части приложения, которая мне нужна.
Кроме того, код для хранения информация о каждом загружаемом файле в базе данных еще не разработана.

Пожалуйста, не могли бы вы объяснить мне, почему моя архитектура неверна? Спасибо :)

Второй
Chmod получает восьмеричное число 777 от ядра symfony; код, размещенный в разделе проблемы, взят из symfony.

Третье

Вы правы, код работает не так, как я ожидал. Он создает папку внутри веб-папки, например: web/web/uploads. Мне нужно получить больше информации о внутренних папках в Symfony. Во всяком случае, ответ @pablo решает мою проблему с этим.


person Isaac Bosca    schedule 26.07.2016    source источник
comment
Прежде всего: у вас плохая архитектура. Не помещайте логику домена в Entity. Второе: chmod получает восьмеричное число в качестве параметра, поэтому вам нужно передать ему 0777. Третье: вы уверены, что именно этот код работает нормально? И этот код делает папку? Почему я спрашиваю? Потому что я думаю, что ваш экземпляр File ничего не знает о вашем Контейнере и поэтому не знает, что это такое %kernel.root_dir%   -  person Michael Sivolobov    schedule 26.07.2016
comment
Привет @MichaelSivolobov, я ценю твой комментарий; по этой причине мне нужно больше информации для улучшения моего кода, теперь я отвечу на каждую часть вашего комментария в основном посте; если можно, скажи мне, почему я не прав. Заранее спасибо.   -  person Isaac Bosca    schedule 27.07.2016


Ответы (1)


То, как вы получаете $path (kernel.root_dir), неверно

Попробуйте этот подход:

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())
    );
}

Пожалуйста, дайте нам знать, если у вас есть прогресс

Привет

Добавлены ссылки на документацию на основе комментария @Isaac:

Более эффективный подход для получения $path:

$this->getParameter('kernel.root_dir') . '/../web/uploads';
person Pablo Rodriguez V.    schedule 27.07.2016
comment
Привет @pablo, твое решение работает для меня, спасибо. Похоже, мой способ получить root dir был неправильным. Спасибо!! Пожалуйста, не могли бы вы опубликовать какую-либо официальную документацию по этим методам $this->get('kernel')->getRootDir(). Большое Вам спасибо :) - person Isaac Bosca; 27.07.2016
comment
Готово, если возникнут проблемы, сообщите - person Pablo Rodriguez V.; 27.07.2016