Как загрузить файл за один вызов веб-сервиса с Symfony2?
В моем Restful API я хочу загрузить файл за один вызов. В моих тестах форма инициализируется и связывается одновременно, но все мои поля данных пусты, и в результате получается пустая запись в моей базе данных.
Если я прохожу через представление формы и затем отправляю его, все в порядке, но я хочу вызвать 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 ответ
Попробуйте разбить эту проблему на простое состояние. Как бы вы опубликовали "текст" или переменную в веб-сервисе с одним постом? Потому что изображение - это просто длинная строка. Проверьте функцию php imagecreatefromstring или imgtostring. Это часто происходит за кулисами ваших протоколов передачи изображений. Как только вы решите более простую проблему, вы докажете, что можете решить свою первоначальную проблему.