Swagger-php: How to upload a multipart/form-data file in application/json request body

Created on 17 Jul 2020  路  9Comments  路  Source: zircote/swagger-php

/**
* @OA\Post(
*      path="/products/save",
*      tags={"Product"},
*      summary="Post bulk products",
*      description="Return bulk products",
*      @OA\RequestBody(
*       required=true,
*       description="Bulk products Body",
*       @OA\JsonContent(
*           @OA\Property(
*               property="products",
*               @OA\Items(
*                  @OA\Property(property="first_name", type="string"),
*                  @OA\Property(property="last_name", type="string"),
*                  @OA\Property(property="email", type="string"),
*                  @OA\Property(property="phone", type="string"),
*                  @OA\MediaType(
*                       mediaType="multipart/form-data",
*                       @OA\Schema(
*                           @OA\Property(
*                               property="resume",
*                               type="file",
*                               format="file"
*                           ),
*                       )
*                  )
*               ),
*           )
*       )
*     ),
* )
*/

Most helpful comment

Finally, I found the way to set a file :

/**
....
     *      @OA\RequestBody(
     *         @OA\MediaType(
     *             mediaType="multipart/form-data",
     *             @OA\Schema(
     *                 @OA\Property(
     *                     description="file to upload",
     *                     property="invoice_file",
     *                     type="string",
     *                     format="binary",
     *                 ),
     *             )
     *         )
     *     ),
...

All 9 comments

I have the same issue, You have to use @OA\Parameter instead of JsonContent, Here my code

    /**
     * @OA\Post(
     *      path="/recoveries/{recovery_reference}/docs",
     *      operationId="recoveriesDocsPost",
     *      tags={"Recoveries Docs"},
     *      summary="Add new doc for given recovery reference",
     *      @OA\Parameter(
     *         name="recovery_reference",
     *         in="path",
     *         description="Recovery reference",
     *         required=true,
     *         @OA\Schema(
     *             type="string",
     *         )
     *      ),
     *      @OA\Parameter(
     *          name="invoice_files_visibility_customer",
     *          description="Visible pour le cr茅ancier ? 1 : Oui, 0 : false",
     *          required=true,
     *          in="query",
     *          example="1",
     *      ),
     *      @OA\Parameter(
     *          name="invoice_files_visibility_debtor",
     *          description="Visible pour le d茅biteur ? 1 : Oui, 0 : false",
     *          required=true,
     *          in="query",
     *          example="1",
     *      ),
     *      @OA\Parameter(
     *          name="invoice_files_type",
     *          description="Type de fichier. 1 : Facture, 4 : Bon de commande, 5 : Contrat, 6 : Devis,7 : Preuve de paiement,8 : Autre",
     *          required=true,
     *          in="query",
     *          example="1",
     *      ),
     *      @OA\Parameter(
     *          @OA\Schema(type="string", format="binary"),
     *          name="invoice_file",
     *          description="Fichier du document",
     *          in="query",
     *      ),
     *
     *      @OA\Response(
     *          response=201,
     *          description="Return doc object",
     *          @OA\JsonContent(ref="#/components/schemas/Doc")
     *       ),
     *       @OA\Response(response=401, description="Unauthorized"),
     *       @OA\Response(response=403, description="Not found or dont have access"),
     *       security={{"bearerAuth": {}}}
     *     )
     *
     */

My problem now when I select a file the execute button dont work

image

My problem now when I select a file the execute button dont work

That sounds like a Swagger-UI issue, and should have nothing to do with Swagger-PHP.

Also, that example will try and transfer the binary content of the file via a query-param, which is severely limited in length. You don't want to send a base64 encoded 1MB PDF in a query-string. Also, since none of the parameters are in the body, using POST has now become pointless since you are not posting a body at all. Would be safe to switch to GET instead.

So that is a solution I can not recommend anyone.

My problem now when I select a file the execute button dont work

That sounds like a Swagger-UI issue, and should have nothing to do with Swagger-PHP.

Also, that example will try and transfer the binary content of the file via a query-param, which is severely limited in length. You don't want to send a base64 encoded 1MB PDF in a query-string. Also, since none of the parameters are in the body, using POST has now become pointless since you are not posting a body at all. Would be safe to switch to GET instead.

So that is a solution I can not recommend anyone.

Thanks @Doqnach for replying
so you can give me an other solution from which i solve my problem and send base64 format of a file in json array

Again, the solution is not in Swagger-PHP or Swagger-UI: the solution is in the implementation code of your client/server. This problem has nothing to do with either of these two libraries.

All you have to do is have your code read the contents of the file, encode it with base64, and put the base64 encoded string into a JSON string field. That is it...

Swagger-UI is nothing more than a visualisation tool for an OpenAPI (c.q. Swagger) specification, with some (limited) testing/executing capabilities. Swagger-PHP is nothing more than a tool to parse PHPDOC and turn it into an OpenAPI (c.q. Swagger) specification. Neither actually provide any actual implementation code whatsoever.

@Doqnach Please can you share a code to upload a file ?

I used this block but I think it's missing a name => https://github.com/zircote/swagger-php/blob/master/Examples/petstore-3.0/controllers/Pet.php#L315-L325

The "code" you linked to is only an example stub without any implementation code whatsoever, showing how Swagger-PHP can parse the docblocks to create the petstore OpenAPI example spec. It is not executable code in any way.

The earlier questions here have all been about "how to upload a file", implying client-side. The petstore example is purely server-side.

I really feel like both of you @kossa and @jeff-cmyk are having a hard time understanding what this (swagger-php) library actually does (generating documentation out of the code you have writting (using PHP docblocks)), or are having trouble making clear what you are actually trying to do.

The most important question here is: are you looking for a server-side solution that Swagger-PHP will document? So looking for how to handle a file uploaded by a 'client'? Or are you looking for an example on how a client can upload a file to a server, and implementation code for said client on how to actually provide that file? If the latter, that totally depends on the programming language that the client will be in, which can be anything and doesn't have to be the same as the server (the thing Swagger-PHP describes) at all.

My biggest problem I'm facing in helping you all is that I don't see any single shred of implementation code showing any form of even the tiniest attempt at trying to solve this problem. All I'm seeing is PHP docblock comments to generate a spec, but that in itself does absolutely nothing without server-side code actually implementing the behaviour the spec describes, or client-side code actually building up the request to the server.

@Doqnach first thank you for helping,

It seems like I was not clear, for my case I finished the implementation of file upload for backend and it works fine with Postman and all other APIs, currently I dont want to share my postman collection with other developer, I want they use Swagger UI, for that I'm sharing/looking PHP docblock comments to generate the spec.

On https://petstore.swagger.io/#/pet/uploadFile the upload file works fine, so I made copy/paste https://github.com/zircote/swagger-php/blob/master/Examples/petstore-3.0/controllers/Pet.php#L290-L326 but I did not get the same UI

By the way my Laravel Code :
image

Postman result :
image

Finally, I found the way to set a file :

/**
....
     *      @OA\RequestBody(
     *         @OA\MediaType(
     *             mediaType="multipart/form-data",
     *             @OA\Schema(
     *                 @OA\Property(
     *                     description="file to upload",
     *                     property="invoice_file",
     *                     type="string",
     *                     format="binary",
     *                 ),
     *             )
     *         )
     *     ),
...

Conclusion: You can't, json doesn't support binary.

You can either send an application/json request (and use base64 encoded string with format="byte")
or don't use json, but a multipart/form-data form and add file uploads with format="binary"

Was this page helpful?
0 / 5 - 0 ratings