上传图像文件FOSRESTBundle

上传图像文件FOSRESTBundle

本文介绍了使用 Symfony2 & 通过 API 上传图像文件FOSRESTBundle的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have been coding an API for a photo sharing app like Instagram using Symfony2, FOSRESTBundle, and Vichuploader for file uploads.

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

I'm able to work around GET and POST requests, but I can't find an example of how to attach to a POST request, the actual image so that in my case, Vichuploader can grab it and help me out with the file upload.

顺便说一句,我可以使用通过使用正常形式提到的堆栈上传文件而不会出现问题.

By the way, I can upload a file without issue using the stack mentioned through the use of a normal form.

推荐答案

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

I have been looking for a solution about the exact same problem. Here is what I did.

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

First let me explain my constraints. I wanted my API to be full JSON and to take power of the HTTP protocol (headers, methods, etc.). I chose to use:

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

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

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

My first thought, because I was thinking JSON everytime, was to encode all the incoming images in base64, then decode them inside my API and store them.

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

The advantage with this solution is that you can pass images along with other data. For instance upload a whole user's profile in one API call. But I read that encoding images in base64 make them grow by 33% of their initial size. I did not wanted my users to be out of mobile data after sending 3 images.

设想的第二种解决方案:表格

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

Then I thought using forms as described above. But I did not know how my clients could send both JSON data (for instance {"last_name":"Litz"}) and image data (for instance image/png one). I know that you can deal with an Content-Type: multipart/form-data but nothing more.

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

Plus I was not using forms in my API since the beginning and I wanted it to be uniform in all my code. [mini-edit: hoho, something I just discovered, here]

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

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

Then, one night, the revelation. I'm using Content-Type: application/json for send JSON data. Why not use image/* to send images? So easy that I searched for days before coming with this idea. This is how I did it (simplified code). Let suppose that the user is calling PUT /api/me/image with a Content-Type: image/*

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

  1. UserController::getUserImageAction(Request $request) - Catching the 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;

  • UserImageService::updateUserImage($user, $content) - 业务逻辑(我把所有东西放在这里是为了更容易阅读)

  • UserImageService::updateUserImage($user, $content) - Business Logic (I put everything here to be simplier to read)

        // 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;
    

  • 这篇关于使用 Symfony2 & 通过 API 上传图像文件FOSRESTBundle的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

    07-23 07:14