Symfony 2 - 在Amazon S3上上传图像的最佳实践

时间:2013-02-13 05:44:46

标签: php upload amazon-s3 symfony-2.1

我有一个表格,我有一个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);
        }
    }

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

现在我需要集成S3层。为此,我想我将使用GaufretteStreamWrapper

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

你会怎么建议这样做?

干杯,

马克西姆

2 个答案:

答案 0 :(得分: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);
    }

}

希望这有帮助

答案 1 :(得分:4)

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