17

我一直在为 Instagram 等照片共享应用程序编写 API,使用 Symfony2、FOSRESTBundle 和 Vichuploader 进行文件上传。

我能够解决 GET 和 POST 请求,但我找不到如何附加到 POST 请求(实际图像)的示例,因此在我的情况下,Vichuploader 可以抓住它并帮助我完成文件上传.

顺便说一句,我可以使用通过使用普通表单提到的堆栈毫无问题地上传文件。

4

4 回答 4

18

我一直在寻找关于完全相同问题的解决方案。这就是我所做的。

首先让我解释一下我的限制。我希望我的 API 是完整的 JSON 并能够使用 HTTP 协议(​​标头、方法等)。我选择使用:

  • Symfony2 用于“几乎为您完成一切,只需编写您的业务逻辑”。
  • Doctrine2 因为默认情况下与 Symfony2 一起使用,并提供了一种通过更改一行来与最流行的 DBMS 集成的方法。
  • FOSRestBundle 来处理我的 API 的 REST 部分(最大限度地利用注释、主体侦听器、支持 JMSSerializer 的响应的自动格式等)。
  • KnpGaufretteBundle 因为我希望能够快速更改存储 blob 文件的方式。

设想的第一个解决方案:base64

因为我每次都在考虑 JSON,所以我的第一个想法是用 base64 编码所有传入的图像,然后在我的 API 中解码它们并存储它们。

此解决方案的优点是您可以将图像与其他数据一起传递。例如,在一次 API 调用中上传整个用户的个人资料。但我读到 base64 编码图像使它们增长了初始大小的 33%。我不希望我的用户在发送 3 张图片后失去移动数据。

设想的第二种解决方案:形式

然后我想使用如上所述的表格。但我不知道我的客户如何同时发送 JSON 数据(例如{"last_name":"Litz"})和图像数据(例如image/png一个)。我知道你可以处理一个Content-Type: multipart/form-data但仅此而已。

另外,我从一开始就没有在我的 API 中使用表单,我希望它在我的所有代码中都是统一的。[迷你编辑:hoho,我刚刚发现的东西,在这里]

第三个也是最后一个解决方案:使用 HTTP..

然后,一晚,天启。我Content-Type: application/json用于发送 JSON 数据。为什么不使用image/*发送图像?如此简单,以至于我在提出这个想法之前搜索了几天。我就是这样做的(简化代码)。假设用户正在PUT /api/me/image使用Content-Type: image/*

  1. UserController::getUserImageAction(Request $request) - 捕获请求

        // get the service to handle the image
        $service = $this->get('service.user_image');
        $content = $request->getContent();
        $userImage = $service->updateUserImage($user, $content);
    
        // get the response from FOSRestBundle::View
        $response = $this->view()->getResponse();
        $response->setContent($content);
        $response->headers->set('Content-Type', $userImage->getMimeType());
    
        return $response;
    
  2. UserImageService::updateUserImage($user, $content) - 业务逻辑(我把所有的东西都放在这里是为了更容易阅读)

        // Create a temporary file on the disk
        // the temp file will be delete at the end of the script
        // see http://www.php.net/manual/en/function.tmpfile.php
        $file = tmpfile();
        if ($file === false) 
            throw new \Exception('File can not be opened.');
    
        // Put content in this file
        $path = stream_get_meta_data($file)['uri'];
        file_put_contents($path, $content);
    
        // the UploadedFile of the user image
        // referencing the temp file (used for validation only)
        $uploadedFile = new UploadedFile($path, $path, null, null, null, true);
    
        // the UserImage to return
        $userImage = $user->getUserImage();
        if (is_null($userImage))
        {
            $userImage = new UserImage();
            $userImage->setOwner($user); 
            // auto persist with my configuration
            // plus generation of a unique ID that allows
            // me to retrieve the image at anytime
            $userImage->setKey(/*random string*/);
        }
    
        // fill the UserImage properties
        $userImage->setImage($uploadedFile);
        $userImage->setMimeType($uploadedFile->getMimeType());
    
        /** @var ConstraintViolationInterface $validationError */
        if (count($this->getValidator()->validate($userImage)) > 0)
            throw new \Exception('Validation');
    
        // if no error we can write the file definitively
        // [KnpGaufretteBundle code to store on disk]
        // [use the UserImage::key to store]
        $this->getEntityManager()->flush();
    
        return $userImage;
    
于 2014-05-23T09:26:43.457 回答
2

您可以通过 FOSRestBundle 对帖子使用表单类型:

例如,您有以下表单类型:

    public function buildForm(FormBuilderInterface $builder, array $options)
{
    $builder
        ->add('facebook_id',
                'text',
                array(
                    'mapped' => FALSE
                )
            )
        ->add('profile_pic',
                'text',
                array(
                    'mapped' => FALSE
                )
            )
        ;

        $builder->addValidator(new CallbackValidator(function(FormInterface $form)
        {
            if ($form["facebook_id"]->getData() === '' || $form["facebook_id"]->getData() === NULL)
            {
                $form->get('facebook_id')->addError(new FormError('facebook_id should not be empty'));
            }
            if ($form["profile_pic"]->getData() === '' || $form["profile_pic"]->getData() === NULL)
            {
                $form->get('profile_pic')->addError(new FormError('profile_pic should not be empty'));
            }
        })
        );

}

public function setDefaultOptions(OptionsResolverInterface $resolver)
{

    $resolver->setDefaults(array(
        // 'validation_constraint' => $collectionConstraint,
        'csrf_protection' => FALSE,
    ));
}

public function getName()
{
    return 'data';
}

然后你可以做的就是将 JSON 发布到 API。执行 POST 时,不要忘记将标头设置为“Content-type = application/json”。

JSON 结构如下所示:

{
"data": {
    "facebook_id": "12345",
    "profile_pic": "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"
}

}

为什么这个 json 包裹在“数据”中?因为您的表单类型在 getName 中也有“数据”,所以它将使用验证等。

我一直在做的是将图片编码为 base64 字符串,同时将它们发送到 API。

然后在 post 函数中,您只需将其转换回来:

$base64     = $form['profile_pic']->getData();
//decode back to image data and create image
$image      = imagecreatefromstring(base64_decode($base64));
imagepng($image, $path);
于 2013-07-29T13:48:35.330 回答
2

这是来自 api 代码位的完整上传。这确实上传了文件,但我仍然无法验证上传的文件。希望这可以帮助。

这将 fosrest 包用于 REST。

private function addResource(Entity $resource) {
    $em = $this->getDoctrine()->getManager();
    $em->persist($resource);
    $em->flush();
}

private function processForm(Entity $resource)
{
    $em = $this->getDoctrine()->getManager();
    $uploadedFile = null;

    $form = $this->createForm(new EntityForm(), $resource);

    foreach ($_FILES as $file) {
        $uploadedFile = new UploadedFile(
            $file['tmp_name'], 
            $file['name'], $file['type'],
            $file['size'], $file['error'], 
            $test = false);
    }

    $submitData = array(
        "file" => $uploadedFile,
    );

    $form->submit($submitData);

    if ($form->isValid()) {
        $repository = $this->getDoctrine()
            ->getRepository('AcmeBundle:Product');

        $view = View::create();
        $resource->setFile($uploadedFile);

        // handling api requests
        if ($this->getRequest()->getMethod() == "POST") {

            $this->addResource($resource);

            // store image url
            $resource = $repository->find($resource->getId());

            if ($resource->getImage()) {
                $fs = new Filesystem();

                if ($fs->exists($resource->getWebPath())) {
                    $resource->setImagePath($resource->getWebPath());    
                }

                $this->addResource($resource);
            }

            $view->setData($resource);
        } 

        return $view;
    }

    return View::create($form);        
}
于 2013-10-31T05:57:55.467 回答
0

上传请求的上传方法示例:

public function uploadAction() {
    $em = $this->getDoctrine()->getManager();

    $document = new Document();

    foreach ($_FILES as $file) {

        $document->setTitle($file['name']);
        $document->file = new UploadedFile($file['tmp_name'], 
                          $file['name'], $file['type'],
                          $file['size'], $file['error'], $test = false);

        $em->persist($document);
        $em->flush();

        break;
    }

    $serializer = $this->get('jms_serializer');
    $data = $serializer->serialize(
          $document, 'json', 
          SerializationContext::create()->setGroups(array('someGroup')));

    return new Response($data);
}

所以这个动作首先将文档存储在服务器上,并返回一个包含文档元数据和路径的 json 响应。我使用响应在我的 Web 应用程序中进行进一步处理。

我对 VichUploader 不熟悉,上面的代码是使用Symfony\Component\HttpFoundation\File\UploadedFile的原生 Symfony2 代码。

阅读:http ://symfony.com/doc/current/cookbook/doctrine/file_uploads.html

于 2013-06-29T03:47:22.260 回答