4

我有一个表单,其中有一个file字段可以上传图像。我需要将此图像上传到 Amazon S3。一步一步地构建这个我开始将图像上传到本地磁盘上,它现在可以工作了。

上传发生在我的实体内部Page,因为建议在保存实体之前测试上传是否成功。我最终得到了这段代码

    /**
     * @ORM\Column(name="objectThumbnail", type="string", length=255, nullable=true)
     */
    protected $objectThumbnail;

    /**
     * This is not a column in the database but it's mapping a field from the form
     *
     * @Assert\File(maxSize="600000000")
     */
    public $file;

    ...

    /**
     * @ORM\PrePersist()
     * @ORM\PreUpdate()
     */
    public function preUpload()
    {
        if (null !== $this->file) {
            // generate a unique filename
            $this->objectThumbnail = $this->getGuid().'.'.$this->file->guessExtension();
        }
    }

    /**
     * @ORM\PostPersist()
     * @ORM\PostUpdate()
     */
    public function upload()
    {
        if (null === $this->file) {
            return;
        }

        // if there is an error when moving the file, an exception will
        // be automatically thrown by move(). This will properly prevent
        // the entity from being persisted to the database on error
        $this->file->move($this->getUploadRootDir(), $this->objectThumbnail);

        unset($this->file);
    }

    /**
     * @ORM\PostRemove()
     */
    public function removeUpload()
    {
        if ($file = $this->getAbsolutePath()) {
            unlink($file);
        }
    }

这是完美的,它就像一个魅力。只是 Symfony(2.1.7)因为属性的公共范围而尖叫file,没什么大不了的。

现在我需要集成 S3 层。为此,我想我会使用Gaufretteand StreamWrapper

现在我正在努力寻找最好的方法。如何访问Filesystem实体中的服务?这样做真的很干净吗?在 Entity 中处理 S3 上图像的上传对我来说感觉有点尴尬。

你会建议怎么做?

干杯,

马克西姆

4

2 回答 2

5

在您的实体中使用服务不是一个好习惯。我建议在本例中创建一个执行验证、持久性和上传的表单处理程序

我写了一个适合你需要的例子

//...
//inside a creation controller action
//...
//create a new page entity
$page = new Page();

//get your page form class
$form = $this->createForm(new PageForm(), $page);

//call your form handler
$formHandler = new PageFormHandler(
        $form,
        $this->get('request'),
        $this->get('your.gaufrette.filesystem'),
        $this->get('your.page.manager')
);

//form is valid ?
if ($formHandler->process()) {         
    //flash message, redirection etc
}

处理程序类

namespace YourCompagnyBundle\Form\Handler;

use YourCompagnyBundle\Entity\Page;
use Symfony\Component\Form\Form;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\File\UploadedFile;
use Gaufrette\Filesystem;


class PageFormHandler
{
    protected $form;
    protected $request;
    protected $pageManager;
    protected $filesystem;

    public function __construct(Form $form, Request $request, Filesystem $filesystem, $pageManager)
    {
        $this->form    = $form;
        $this->request = $request;
        $this->filesystem = $filesystem;
        $this->pageManager = $pageManager;
    }

    public function process()
    {
        if( $this->request->getMethod() == 'POST' )
        {
            $this->form->bind($this->request);

            if( $this->form->isValid() )
            {
               $this->onSuccess($this->form->getData());               

                return true;
            }
        }

        return false;
    }

    function onSuccess(Page $page)
    {
        //has uploaded file ?
        if($page->getFile() instanceof UploadedFile){
            //do some logic with gaufrette filesystem
           //if page is already managed in database (update), delete previous file


        }
        //storage
        $this->pageManager->save($page);
    }

}

希望这有帮助

于 2013-02-15T22:55:11.393 回答
4

也许你应该检查一下VichUploaderBundle,它基本上将 File 对象注入到你的实体中,并且与 Gaufrette 的集成非常容易。

于 2013-02-17T17:32:06.627 回答