Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File upload via JSON:API in drupal #61

Open
dreamsbond opened this issue Nov 4, 2019 · 4 comments
Open

File upload via JSON:API in drupal #61

dreamsbond opened this issue Nov 4, 2019 · 4 comments

Comments

@dreamsbond
Copy link

I found an article mentioned about File Upload via JSON:API at https://www.drupal.org/node/3024331, curious if limoncello-app support such implementation?

@neomerx
Copy link
Collaborator

neomerx commented Nov 5, 2019

Yes, it does. There is nothing special about file uploads really. A controller handler will receive a $request parameter which would have file attachment. When the file is stored and some ID is assigned it's time to return the JSON API response.

$index       = ...;
$requestUri  = $request->getUri();
$crud        = static::defaultCreateApi($container, static::API_CLASS);
$jsonSchemas = $container->get(JsonSchemasInterface::class);
$encoder     = $container->get(EncoderInterface::class);

return static::defaultCreateResponse($index, $requestUri, $crud, $jsonSchemas, $encoder);

The code is taken from here and here.

@dreamsbond
Copy link
Author

Could you provide an example?

@neomerx
Copy link
Collaborator

neomerx commented Nov 14, 2019

Code for controller

    // NOTE: you need to create a model/schema/routes/auth rules/etc for uploaded files. Just like for users, roles or any other resource.
    
    /**
     * @inheritdoc
     */
    public static function create(
        array $routeParams,
        ContainerInterface $container,
        ServerRequestInterface $request
    ): ResponseInterface {
        $files = $request->getUploadedFiles();
        if (count($files) !== 1 ||
            (($file = reset($files)) instanceof UploadedFileInterface) === false
        ) {
            return new EmptyResponse(422);
        }

        assert($file instanceof UploadedFileInterface);

        // save the file and assign file ID (this one stores to tmp, you'd better to save to some storage)
        $fileName = tempnam(sys_get_temp_dir(), 'my_prefix');
        if ($fileName === false ||
            file_put_contents($fileName, (string)$file->getStream()) === false
        ) {
            return new EmptyResponse(400);
        }
        $fileId = pathinfo($fileName, PATHINFO_FILENAME);
        
        // here you need to save the data to the database or maybe leave it as it is. Because on the next step
        // `defaultCreateResponse` will try to read the resource by `$fileId` via API so it should return
        // the resource.
        
        return static::defaultCreateResponse(
            $fileId,
            $request->getUri(),
            static::defaultCreateApi($container, static::API_CLASS),
            $container->get(SettingsProviderInterface::class),
            $container->get(JsonSchemasInterface::class),
            $container->get(EncoderInterface::class)
        );
    }

Code for a test

    public function testUpload(): void
    {
        $file = new UploadedFile(new Stream(__FILE__), filesize(__FILE__), UPLOAD_ERR_OK);

        $response = $this->call('POST', static::API_URI, [], [], [], [], [$file]);
    }

@dreamsbond
Copy link
Author

thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants