如何使用Symfony2在一个Web服务调用中上传文件?

时间:2012-11-16 17:10:52

标签: php web-services api symfony restful-architecture

在我的Restful API中,我想在一次调用中上传文件。 在我的测试中,表单被同时初始化和绑定,但我的所有数据字段形式都是空的,结果是我的数据库中的空记录。

如果我通过表单视图然后提交它,一切都很好,但我想在一次调用中调用Webservice。 Web服务的目标是由骨干应用程序使用。

感谢您的帮助。

我的测试:

$client = static::createClient();
$photo = new UploadedFile(
        '/Userdirectory/test.jpg',
        'photo.jpg',
        'image/jpeg',
        14415
);
$crawler = $client->request('POST', '/ws/upload/mydirectory', array(), array('form[file]' => $photo), array('Content-Type'=>'multipart/formdata'));

我的控制器有动作:

public function uploadAction(Request $request, $directory, $_format)
{
    $document = new Media();
    $document->setDirectory($directory);
    $form = $this->createFormBuilder($document, array('csrf_protection' => false))
        /*->add('directory', 'hidden', array(
             'data' => $directory
        ))*/
        ->add('file')
        ->getForm()
    ;
    if ($this->getRequest()->isMethod('POST')) {

        $form->bind($request);
        if ($form->isValid()) {
            $em = $this->getDoctrine()->getManager();
            $em->persist($document);
            $em->flush();
            if($document->getId() !== '')
                return $this->redirect($this->generateUrl('media_show', array('id'=>$document->getId(), 'format'=>$_format)));
        }else{
            $response = new Response(serialize($form->getErrors()), 406);
            return $response;
        }
   }

    return array('form' => $form->createView());
}

我的媒体实体:

    <?php

    namespace MyRestBundle\RestBundle\Entity;
    use Symfony\Component\Serializer\Normalizer\NormalizableInterface;
    use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
    use Doctrine\ORM\Mapping as ORM;
    use Symfony\Component\Validator\Constraints as Assert;
    use Symfony\Component\HttpFoundation\File\UploadedFile;
    use Symfony\Component\HttpFoundation\Request;
    /**
     * @ORM\Entity
     * @ORM\HasLifecycleCallbacks
     */
    class Media
    {
        /**
         * @ORM\Id
         * @ORM\Column(type="integer")
         * @ORM\GeneratedValue(strategy="AUTO")
         */
        protected $id;

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

        public $directory;

        /**
         * @Assert\File(maxSize="6000000")
         */
        public $file;

        /**
         * @see \Symfony\Component\Serializer\Normalizer\NormalizableInterface
         */
        function normalize(NormalizerInterface $normalizer, $format= null)
        {
            return array(
                'path' => $this->getPath()
            );
        }

        /**
         * @see
         */
        function denormalize(NormalizerInterface $normalizer, $data, $format = null)
        {
            if (isset($data['path']))
            {
                $this->setPath($data['path']);
            }
        }

        protected function getAbsolutePath()
        {
            return null === $this->path ? null : $this->getUploadRootDir().'/'.$this->path;
        }

        protected function getWebPath()
        {
            return null === $this->path ? null : $this->getUploadDir().'/'.$this->path;
        }

        protected function getUploadRootDir()
        {
            // the absolute directory path where uploaded documents should be saved
            return __DIR__.'/../../../../web/'.$this->getUploadDir();
        }

        protected function getUploadDir()
        {
            // get rid of the __DIR__ so it doesn't screw when displaying uploaded doc/image in the view.
            return 'uploads/'.(null === $this->directory ? 'documents' : $this->directory);
        }

        /**
         * @ORM\PrePersist()
         * @ORM\PreUpdate()
         */
        public function preUpload()
        {
            if (null !== $this->file) {
                // do whatever you want to generate a unique name
                $this->path = $this->getUploadDir().'/'.sha1(uniqid(mt_rand(), true)).'.'.$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->path);

            unset($this->file);
        }

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

        /**
         * Set Directory
         *
         * @param string $directory
         * @return Media
         */
        public function setDirectory($directory)
        {
            $this->directory = $directory;

            return $this;
        }

        /**
         * Set Path
         *
         * @param string $path
         * @return Media
         */
        public function setPath($path)
        {
            $this->path = $path;

            return $this;
        }

        /**
         * Get path
         *
         * @return string
         */
        public function getPath()
        {
            $request = Request::createFromGlobals();
            return $request->getHost().'/'.$this->path;
        }

        /**
         * Get id
         *
         * @return string
         */
        public function getId()
        {
            return $this->id;
        }
    }

我的路线:

upload_dir_media:
  pattern:      /upload/{directory}.{_format}
  defaults:     { _controller: MyRestBundle:Media:upload, _format: html }
  requirements: { _method: POST }

1 个答案:

答案 0 :(得分:0)

尝试将此问题分解为简单状态。如何使用一个帖子将“文本”或变量发布到Web服务?因为图像只是一个长串。查看php函数imagecreatefromstringimgtostring。这通常是你的图像传输协议的幕后故事。一旦你解决了这个更简单的问题,你就会证明你可以解决你原来的问题。