api-platform / core

The server component of API Platform: hypermedia and GraphQL APIs in minutes
https://api-platform.com
MIT License
2.43k stars 864 forks source link

File upload not working although following documentation #2726

Closed GRUXXKi closed 5 years ago

GRUXXKi commented 5 years ago

I've trying to find out what I've been doing wrong but I really can't solved it.

I've installed symfony following the documentation and started to write my code. Everything is really great and after having installed successfully the JWT token, I'm starting to handle the file uploading !

Here is my Symfony.lock :

{
    "api-platform/api-pack": {
        "version": "v1.2.0"
    },
    "api-platform/core": {
        "version": "2.1",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "2.1",
            "ref": "18727d8f229306860b46955f438e1897421da689"
        },
        "files": [
            "config/packages/api_platform.yaml",
            "config/routes/api_platform.yaml",
            "src/Entity/.gitignore"
        ]
    },
    "behat/transliterator": {
        "version": "v1.2.0"
    },
    "doctrine/annotations": {
        "version": "1.0",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "1.0",
            "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672"
        },
        "files": [
            "config/routes/annotations.yaml"
        ]
    },
    "doctrine/cache": {
        "version": "v1.8.0"
    },
    "doctrine/collections": {
        "version": "v1.5.0"
    },
    "doctrine/common": {
        "version": "v2.10.0"
    },
    "doctrine/data-fixtures": {
        "version": "v1.3.1"
    },
    "doctrine/dbal": {
        "version": "v2.9.2"
    },
    "doctrine/doctrine-bundle": {
        "version": "1.6",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "1.6",
            "ref": "453e89b78ded666f351617baca5ae40d20622351"
        },
        "files": [
            "config/packages/doctrine.yaml",
            "config/packages/prod/doctrine.yaml",
            "src/Entity/.gitignore",
            "src/Repository/.gitignore"
        ]
    },
    "doctrine/doctrine-cache-bundle": {
        "version": "1.3.5"
    },
    "doctrine/doctrine-fixtures-bundle": {
        "version": "3.0",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "3.0",
            "ref": "fc52d86631a6dfd9fdf3381d0b7e3df2069e51b3"
        },
        "files": [
            "src/DataFixtures/AppFixtures.php"
        ]
    },
    "doctrine/doctrine-migrations-bundle": {
        "version": "1.2",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "1.2",
            "ref": "c1431086fec31f17fbcfe6d6d7e92059458facc1"
        },
        "files": [
            "config/packages/doctrine_migrations.yaml",
            "src/Migrations/.gitignore"
        ]
    },
    "doctrine/event-manager": {
        "version": "v1.0.0"
    },
    "doctrine/inflector": {
        "version": "v1.3.0"
    },
    "doctrine/instantiator": {
        "version": "1.2.0"
    },
    "doctrine/lexer": {
        "version": "v1.0.1"
    },
    "doctrine/migrations": {
        "version": "v2.0.0"
    },
    "doctrine/orm": {
        "version": "v2.6.3"
    },
    "doctrine/persistence": {
        "version": "v1.1.0"
    },
    "doctrine/reflection": {
        "version": "v1.0.0"
    },
    "egulias/email-validator": {
        "version": "2.1.7"
    },
    "fig/link-util": {
        "version": "1.0.0"
    },
    "friendsofsymfony/user-bundle": {
        "version": "v2.1.2"
    },
    "fzaninotto/faker": {
        "version": "v1.8.0"
    },
    "gedmo/doctrine-extensions": {
        "version": "v2.4.36"
    },
    "jdorn/sql-formatter": {
        "version": "v1.2.17"
    },
    "jms/metadata": {
        "version": "2.0.0"
    },
    "lcobucci/jwt": {
        "version": "3.2.5"
    },
    "lexik/jwt-authentication-bundle": {
        "version": "2.5",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "2.5",
            "ref": "509b1542f3180a1cfe248ade8b7bf5092c2d4127"
        },
        "files": [
            "config/packages/lexik_jwt_authentication.yaml"
        ]
    },
    "namshi/jose": {
        "version": "7.2.3"
    },
    "nelmio/cors-bundle": {
        "version": "1.5",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "1.5",
            "ref": "f0436fc35fca88eada758311f8de43bfb61f1980"
        },
        "files": [
            "config/packages/nelmio_cors.yaml"
        ]
    },
    "nikic/php-parser": {
        "version": "v4.2.1"
    },
    "ocramius/package-versions": {
        "version": "1.4.0"
    },
    "ocramius/proxy-manager": {
        "version": "2.2.2"
    },
    "phpdocumentor/reflection-common": {
        "version": "1.0.1"
    },
    "phpdocumentor/reflection-docblock": {
        "version": "4.3.0"
    },
    "phpdocumentor/type-resolver": {
        "version": "0.4.0"
    },
    "psr/cache": {
        "version": "1.0.1"
    },
    "psr/container": {
        "version": "1.0.0"
    },
    "psr/link": {
        "version": "1.0.0"
    },
    "psr/log": {
        "version": "1.1.0"
    },
    "psr/simple-cache": {
        "version": "1.0.1"
    },
    "ramsey/uuid": {
        "version": "3.8.0"
    },
    "sensio/framework-extra-bundle": {
        "version": "5.2",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "5.2",
            "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
        },
        "files": [
            "config/packages/sensio_framework_extra.yaml"
        ]
    },
    "stof/doctrine-extensions-bundle": {
        "version": "1.2",
        "recipe": {
            "repo": "github.com/symfony/recipes-contrib",
            "branch": "master",
            "version": "1.2",
            "ref": "6c1ceb662f8997085f739cd089bfbef67f245983"
        },
        "files": [
            "config/packages/stof_doctrine_extensions.yaml"
        ]
    },
    "swiftmailer/swiftmailer": {
        "version": "v6.2.0"
    },
    "symfony/asset": {
        "version": "v4.2.4"
    },
    "symfony/cache": {
        "version": "v4.2.4"
    },
    "symfony/config": {
        "version": "v4.2.4"
    },
    "symfony/console": {
        "version": "3.3",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "3.3",
            "ref": "0fa049c19069a65f52c1c181d64be3de672c1504"
        },
        "files": [
            "bin/console",
            "config/bootstrap.php"
        ]
    },
    "symfony/contracts": {
        "version": "v1.0.2"
    },
    "symfony/debug": {
        "version": "v4.2.4"
    },
    "symfony/dependency-injection": {
        "version": "v4.2.4"
    },
    "symfony/doctrine-bridge": {
        "version": "v4.2.4"
    },
    "symfony/dotenv": {
        "version": "v4.2.4"
    },
    "symfony/event-dispatcher": {
        "version": "v4.2.4"
    },
    "symfony/expression-language": {
        "version": "v4.2.4"
    },
    "symfony/filesystem": {
        "version": "v4.2.4"
    },
    "symfony/finder": {
        "version": "v4.2.4"
    },
    "symfony/flex": {
        "version": "1.0",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "1.0",
            "ref": "dc3fc2e0334a4137c47cfd5a3ececc601fa61a0b"
        },
        "files": [
            ".env"
        ]
    },
    "symfony/form": {
        "version": "v4.2.4"
    },
    "symfony/framework-bundle": {
        "version": "4.2",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "4.2",
            "ref": "9aafbc8edf7558dfe213e9d51d0217cbd78acc5a"
        },
        "files": [
            "config/bootstrap.php",
            "config/packages/cache.yaml",
            "config/packages/framework.yaml",
            "config/packages/test/framework.yaml",
            "config/services.yaml",
            "public/index.php",
            "src/Controller/.gitignore",
            "src/Kernel.php"
        ]
    },
    "symfony/http-foundation": {
        "version": "v4.2.4"
    },
    "symfony/http-kernel": {
        "version": "v4.2.4"
    },
    "symfony/inflector": {
        "version": "v4.2.4"
    },
    "symfony/intl": {
        "version": "v4.2.4"
    },
    "symfony/maker-bundle": {
        "version": "1.0",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "1.0",
            "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
        }
    },
    "symfony/options-resolver": {
        "version": "v4.2.4"
    },
    "symfony/orm-pack": {
        "version": "v1.0.6"
    },
    "symfony/polyfill-intl-icu": {
        "version": "v1.11.0"
    },
    "symfony/polyfill-intl-idn": {
        "version": "v1.11.0"
    },
    "symfony/polyfill-mbstring": {
        "version": "v1.10.0"
    },
    "symfony/polyfill-php72": {
        "version": "v1.11.0"
    },
    "symfony/process": {
        "version": "v4.2.4"
    },
    "symfony/profiler-pack": {
        "version": "v1.0.4"
    },
    "symfony/property-access": {
        "version": "v4.2.4"
    },
    "symfony/property-info": {
        "version": "v4.2.4"
    },
    "symfony/routing": {
        "version": "4.2",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "4.2",
            "ref": "5374e24d508ba8fd6ba9eb15170255fdb778316a"
        },
        "files": [
            "config/packages/dev/routing.yaml",
            "config/packages/routing.yaml",
            "config/packages/test/routing.yaml",
            "config/routes.yaml"
        ]
    },
    "symfony/security-bundle": {
        "version": "3.3",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "3.3",
            "ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527"
        },
        "files": [
            "config/packages/security.yaml"
        ]
    },
    "symfony/security-core": {
        "version": "v4.2.4"
    },
    "symfony/security-csrf": {
        "version": "v4.2.4"
    },
    "symfony/security-guard": {
        "version": "v4.2.4"
    },
    "symfony/security-http": {
        "version": "v4.2.4"
    },
    "symfony/serializer": {
        "version": "v4.2.4"
    },
    "symfony/stopwatch": {
        "version": "v4.2.4"
    },
    "symfony/swiftmailer-bundle": {
        "version": "2.5",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "2.5",
            "ref": "3db029c03e452b4a23f7fc45cec7c922c2247eb8"
        },
        "files": [
            "config/packages/dev/swiftmailer.yaml",
            "config/packages/swiftmailer.yaml",
            "config/packages/test/swiftmailer.yaml"
        ]
    },
    "symfony/templating": {
        "version": "v4.2.4"
    },
    "symfony/translation": {
        "version": "3.3",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "3.3",
            "ref": "1fb02a6e1c8f3d4232cce485c9afa868d63b115a"
        },
        "files": [
            "config/packages/translation.yaml",
            "translations/.gitignore"
        ]
    },
    "symfony/twig-bridge": {
        "version": "v4.2.4"
    },
    "symfony/twig-bundle": {
        "version": "3.3",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "3.3",
            "ref": "369b5b29dc52b2c190002825ae7ec24ab6f962dd"
        },
        "files": [
            "config/packages/twig.yaml",
            "config/routes/dev/twig.yaml",
            "templates/base.html.twig"
        ]
    },
    "symfony/validator": {
        "version": "4.1",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "4.1",
            "ref": "0cdc982334f45d554957a6167e030482795bf9d7"
        },
        "files": [
            "config/packages/validator.yaml"
        ]
    },
    "symfony/var-dumper": {
        "version": "v4.2.4"
    },
    "symfony/var-exporter": {
        "version": "v4.2.4"
    },
    "symfony/web-link": {
        "version": "v4.2.4"
    },
    "symfony/web-profiler-bundle": {
        "version": "3.3",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "3.3",
            "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
        },
        "files": [
            "config/packages/dev/web_profiler.yaml",
            "config/packages/test/web_profiler.yaml",
            "config/routes/dev/web_profiler.yaml"
        ]
    },
    "symfony/web-server-bundle": {
        "version": "3.3",
        "recipe": {
            "repo": "github.com/symfony/recipes",
            "branch": "master",
            "version": "3.3",
            "ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a"
        }
    },
    "symfony/yaml": {
        "version": "v4.2.4"
    },
    "twig/twig": {
        "version": "v2.7.3"
    },
    "vich/uploader-bundle": {
        "version": "1.5",
        "recipe": {
            "repo": "github.com/symfony/recipes-contrib",
            "branch": "master",
            "version": "1.5",
            "ref": "c4f5755b37fb65b9c6a3cbdae91205c15a137ed4"
        },
        "files": [
            "config/packages/vich_uploader.yaml"
        ]
    },
    "webmozart/assert": {
        "version": "1.4.0"
    },
    "willdurand/negotiation": {
        "version": "v2.3.1"
    },
    "zendframework/zend-code": {
        "version": "3.3.1"
    },
    "zendframework/zend-eventmanager": {
        "version": "3.2.1"
    }
}

For test, I've followed exactly the documentation here : https://api-platform.com/docs/core/file-upload/

But now when I try to send something, here is the result I've got:

{ "@context": "/api/contexts/Error", "@type": "hydra:Error", "hydra:title": "An error occurred", "hydra:description": "No identifiers defined for resource of type \"App\Entity\MediaObject\"", "trace": [ { "namespace": "", "short_class": "", "class": "", "type": "", "function": "", "file": "/MyAmasingApp/api/vendor/api-platform/core/src/Bridge/Symfony/Routing/IriConverter.php", "line": 184, "args": [] }, { "namespace": "ApiPlatform\Core\Bridge\Symfony\Routing", "short_class": "IriConverter", "class": "ApiPlatform\Core\Bridge\Symfony\Routing\IriConverter", "type": "->", "function": "generateIdentifiersUrl", "file": "MyAmasingApp/api/vendor/api-platform/core/src/Bridge/Symfony/Routing/IriConverter.php", "line": 122, "args": [ [ "array", [] ], [ "string", "App\Entity\MediaObject" ] ] }, { "namespace": "ApiPlatform\Core\Bridge\Symfony\Routing", "short_class": "IriConverter", "class": "ApiPlatform\Core\Bridge\Symfony\Routing\IriConverter", "type": "->", "function": "getIriFromItem", "file": "/MyAmasingApp/api/vendor/api-platform/core/src/EventListener/WriteListener.php", "line": 80, "args": [ [ "object", "App\Entity\MediaObject" ] ] }, { "namespace": "ApiPlatform\Core\EventListener", "short_class": "WriteListener", "class": "ApiPlatform\Core\EventListener\WriteListener", "type": "->", "function": "onKernelView", "file": "/MyAmasingApp/api/vendor/symfony/event-dispatcher/Debug/WrappedListener.php", "line": 115, "args": [ [ "object", "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" ], [ "string", "kernel.view" ], [ "object", "Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher" ] ] }, { "namespace": "Symfony\Component\EventDispatcher\Debug", "short_class": "WrappedListener", "class": "Symfony\Component\EventDispatcher\Debug\WrappedListener", "type": "->", "function": "__invoke", "file": "/MyAmasingApp/api/vendor/symfony/event-dispatcher/EventDispatcher.php", "line": 212, "args": [ [ "object", "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" ], [ "string", "kernel.view" ], [ "object", "Symfony\Component\HttpKernel\Debug\TraceableEventDispatcher" ] ] }, { "namespace": "Symfony\Component\EventDispatcher", "short_class": "EventDispatcher", "class": "Symfony\Component\EventDispatcher\EventDispatcher", "type": "->", "function": "doDispatch", "file": "/MyAmasingApp/api/vendor/symfony/event-dispatcher/EventDispatcher.php", "line": 44, "args": [ [ "array", [ [ "object", "Symfony\Component\EventDispatcher\Debug\WrappedListener" ], [ "object", "Symfony\Component\EventDispatcher\Debug\WrappedListener" ], [ "object", "Symfony\Component\EventDispatcher\Debug\WrappedListener" ], [ "object", "Symfony\Component\EventDispatcher\Debug\WrappedListener" ], [ "object", "Symfony\Component\EventDispatcher\Debug\WrappedListener" ], [ "object", "Symfony\Component\EventDispatcher\Debug\WrappedListener" ], [ "object", "Symfony\Component\EventDispatcher\Debug\WrappedListener" ] ] ], [ "string", "kernel.view" ], [ "object", "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" ] ] }, { "namespace": "Symfony\Component\EventDispatcher", "short_class": "EventDispatcher", "class": "Symfony\Component\EventDispatcher\EventDispatcher", "type": "->", "function": "dispatch", "file": "/MyAmasingApp/api/vendor/symfony/event-dispatcher/Debug/TraceableEventDispatcher.php", "line": 145, "args": [ [ "string", "kernel.view" ], [ "object", "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" ] ] }, { "namespace": "Symfony\Component\EventDispatcher\Debug", "short_class": "TraceableEventDispatcher", "class": "Symfony\Component\EventDispatcher\Debug\TraceableEventDispatcher", "type": "->", "function": "dispatch", "file": "/MyAmasingApp/api/vendor/symfony/http-kernel/HttpKernel.php", "line": 155, "args": [ [ "string", "kernel.view" ], [ "object", "Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent" ] ] }, { "namespace": "Symfony\Component\HttpKernel", "short_class": "HttpKernel", "class": "Symfony\Component\HttpKernel\HttpKernel", "type": "->", "function": "handleRaw", "file": "/MyAmasingApp/api/vendor/symfony/http-kernel/HttpKernel.php", "line": 67, "args": [ [ "object", "Symfony\Component\HttpFoundation\Request" ], [ "integer", 1 ] ] }, { "namespace": "Symfony\Component\HttpKernel", "short_class": "HttpKernel", "class": "Symfony\Component\HttpKernel\HttpKernel", "type": "->", "function": "handle", "file": "/MyAmasingApp/api/vendor/symfony/http-kernel/Kernel.php", "line": 198, "args": [ [ "object", "Symfony\Component\HttpFoundation\Request" ], [ "integer", 1 ], [ "boolean", true ] ] }, { "namespace": "Symfony\Component\HttpKernel", "short_class": "Kernel", "class": "Symfony\Component\HttpKernel\Kernel", "type": "->", "function": "handle", "file": "/MyAmasingApp/api/public/index.php", "line": 25, "args": [ [ "object", "Symfony\Component\HttpFoundation\Request" ] ] } ] }

Any idea ?

teohhanhui commented 5 years ago

Sorry that it's not mentioned in the docs, but you need an id for the MediaObject. I'll update the docs to include that.

Please let me know if everything works after that.

GRUXXKi commented 5 years ago

Sure, id is mandatory for Entity management. So I've added one already.

Here is my MediaObject entity :

<?php

namespace App\Entity;

use ApiPlatform\Core\Annotation\ApiProperty;
use ApiPlatform\Core\Annotation\ApiResource;
use App\Controller\CreateMediaObjectAction;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Symfony\Component\Serializer\Annotation\Groups;
use Symfony\Component\Validator\Constraints as Assert;
use Vich\UploaderBundle\Mapping\Annotation as Vich;

/**
 * @ORM\Entity
 * @ApiResource(iri="http://schema.org/MediaObject", *
 *     collectionOperations={
 *         "get",
 *         "post"={
 *              "method"="POST",
 *              "controller"=CreateMediaObjectAction::class,
 *              "defaults"={"_api_receive"=false},
 *              "access_control"="is_granted('ROLE_ORGANIZER')||is_granted('ROLE_ADMIN')",
 *              "validation_groups"={"Default", "media_object_create"}, *
 *              "swagger_context"={
 *                 "consumes"={
 *                     "multipart/form-data",
 *                 },
 *                 "parameters"={
 *                     {
 *                         "in"="formData",
 *                         "name"="file",
 *                         "type"="file",
 *                         "description"="The file to upload",
 *                     },
 *                 },
 *             },
 *         },
 *     },
 *     itemOperations={
 *         "get",
 *     },
 * )
 * @Vich\Uploadable
 */
class MediaObject
{
    /**
     * @ORM\Id()
     * @ORM\GeneratedValue()
     * @ORM\Column(type="integer")
     */
    private $id;

    /**
     * @var string|null
     *
     * @ApiProperty(iri="http://schema.org/contentUrl")
     * @Groups({"media_object_read"})
     */
    public $contentUrl;

    /**
     * @var File|null
     *
     * @Assert\NotNull(groups={"media_object_create"})
     * @Vich\UploadableField(mapping="media_object", fileNameProperty="filePath")
     */
    public $file;

    /**
     * @var string|null
     *
     * @ORM\Column(nullable=true)
     */
    public $filePath;
}
GRUXXKi commented 5 years ago

Sorry I just saw that my id is private and no get/set....

teohhanhui commented 5 years ago

Addressed in https://github.com/api-platform/docs/pull/786