dking3876
4/30/2018 - 8:00 PM

Add POST endpoint for performant Drupal 8 REST file uploads

Add POST endpoint for performant Drupal 8 REST file uploads

Instead of accepting serialized files, I wanted to process file uploads as multipart/form-data.

I also wanted to use the crsf prevention API.

This is what I came up with.  Replace `modulename` with your module and `fileupload` with whatever you want to name your class/endpoint.

In your routing.yml:

```yml

modulename.fileupload:
  path: 'fileupload'
  defaults: { _controller: '\Drupal\modulename\Controller\FileUploadController::create' }
  methods:  [POST]
  requirements:
    _custom_access: '\Drupal\modulename\Controller\FileUploadController::access'
```

In your services.yml:

```yml
services:
  modulename.route_subscriber:
    class: Drupal\modulename\Routing\RouteSubscriber
    tags:
      - { name: event_subscriber }
```

In src/Routing/RouteSubscriber.php:

```php
<?php
namespace Drupal\modulename\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Alter modules's route(s).
 */
class RouteSubscriber extends RouteSubscriberBase {
  /**
   * {@inheritdoc}
   *
   * Add a CSRF-Token requirement to the fileupload route.
   */
  public function alterRoutes(RouteCollection $collection) {
    if ($route = $collection->get('modulename.fileupload')) {
      $route->setRequirement('_access_rest_csrf', 'TRUE');
    }
  }
}
```

In src/Controller/FileUploadController.php

```php
<?php
namespace Drupal\modulename\Controller;

use Drupal\Core\Session\AccountInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\JsonResponse;
use Drupal\Core\Access\AccessResult;

/**
 * Process file uploads.
 */
class FileUploadController {

  /**
   * Allow access for logged-in, authenitcated users.
   *
   * @param \Drupal\Core\Session\AccountInterface $account
   *   Run access checks for this account.
   */
  public function access(AccountInterface $account) {
    return AccessResult::allowedIf($account->isAuthenticated());
  }

  /**
   * Process posted files.
   */
  public function create(Request $request) {
    if (strpos($request->headers->get('Content-Type'), 'multipart/form-data;') !== 0) {
      $res = new JsonResponse();
      $res->setStatusCode(400, 'must submit multipart/form-data');
      return $res;
    }

    $data = file_get_contents($_FILES['image']['tmp_name']);
    $mime = $_FILES['image']['type'];

    $file = file_save_data($data, NULL, FILE_EXISTS_REPLACE);

    $response['file_id'] = $file->id();

    return new JsonResponse($response);
  }


}
```