Support JSON/REST multipart/form-data uploads

Created on 20 November 2018, over 5 years ago
Updated 22 May 2024, 24 days ago

Problem/Motivation

This is a follow-up of #1927648: Allow creation of file entities from binary data via REST requests which added support for uploading file through a REST endpoint.

The implementation only support file transferred with the Content-Type: application/octet-stream.

It's also possible (and widely used) to upload file using Content-Type: multipart/form-data.

Some client libraries, such as ngx-uploader for Angular projects, only support the multipart way.

Proposed resolution

It's valid to consider that the burden should be on client library and that it's up to it to be compatible with the simple binary way, but it's also valid to want to have both use cases supported by Drupal.

I think we should add a basic support for multipart/form-data uploads, which can at first be limited to only 1 file per request to reduce scope & complexity.

Remaining tasks

Declare a new format alongside "bin" to match multipart content-type and handle such requests.

Feature request
Status

Needs work

Version

11.0 🔥

Component
File module 

Last updated 3 days ago

Created by

🇨🇦Canada garphy

Live updates comments and jobs are added and updated live.
  • Needs tests

    The change is currently missing an automated test that fails when run with the original code, and succeeds when the bug has been fixed.

Sign in to follow issues

Comments & Activities

Not all content is available!

It's likely this issue predates Contrib.social: some issue and comment data are missing.

  • 🇻🇳Vietnam Chương Phạm

    The patch work for me but I have to change

    $fileKey = 'file';
    

    to

    $fileKey = $request->files->getIterator()->key();
    
  • 🇫🇷France Guicom

    Update patch for Drupal 10.1.5

  • last update 8 months ago
    Custom Commands Failed
  • last update 8 months ago
    Patch Failed to Apply
  • 🇮🇳India _utsavsharma

    Patch for 11.x.

  • last update 8 months ago
    Custom Commands Failed
  • 🇮🇳India vsujeetkumar Delhi

    Fixed the failures (CCF Issues) in #27.

  • last update 7 months ago
    30,423 pass, 10 fail
  • I think the patch needs to be updated, it uses getContentType() to check for bin_multipart. The getContentType is now deprecated and we need to use getContentTypeFormat. That uses format and has a fixed set of keys mapped to mime type.

    static::$formats = [
      'html' => ['text/html', 'application/xhtml+xml'],
      'txt' => ['text/plain'],
      'js' => ['application/javascript', 'application/x-javascript', 'text/javascript'],
      'css' => ['text/css'],
      'json' => ['application/json', 'application/x-json'],
      'jsonld' => ['application/ld+json'],
      'xml' => ['text/xml', 'application/xml', 'application/x-xml'],
      'rdf' => ['application/rdf+xml'],
      'atom' => ['application/atom+xml'],
      'rss' => ['application/rss+xml'],
      'form' => ['application/x-www-form-urlencoded', 'multipart/form-data'],
    ];
    

    So It will always return 'form' in this use-case, so I think we need to use the new method and replace checks for bin_multipart with form.
    Since I'm running into this problem for my project I'll see I can put a new patch together.

  • As described above, I've update the patch for 10.1 to check for 'form' format instead of the bin_multipart that was added in previous patches in this issue.

  • last update 6 months ago
    Patch Failed to Apply
  • 🇫🇷France Guicom

    Update patch for Drupal 10.2.3 including fix in #30

  • 🇫🇷France Guicom

    Fix previous patch, wrong argument order in jsonapi.services.yml.

  • My multipart/form-data upload is still failing with the latest patch.
    The Content-Disposition header with filename is now mandatory, which I can somewhat understand. It is just annoying that a different party is using our REST interface and they need to change their code.

    But even with the Content-Disposition header set, the upload still fails on trying to move the temporary file. It claims it doesn't exist but that is because it uses the OriginalName to find the tmp file and not the actual path of the tmp file.

    In FileUploadResource:
    $temp_file_path = $this->streamUploadData($request);

    The patch now returns
    return basename($file->getClientOriginalName());

    Shouldn't it return $file->getPathname();
    I would say yes, but as I just glanced at the Symfony class I might be missing something.
    It would be a simple fix, so I'm testing it and will upload a new patch soon.

    I am a bit worried about Drupal 10.3 though, will look into that soon as it seems to refactor some relevant code and rerolling the patch will probably take a bit of time.

  • Added a new patch for Drupal 10.2.
    Like I said in my previous comment, changed the return value of streamUploadData to return the path instead of the originalName.

    I'll soon try to make some time to look into how drupal 10.3 affects this issue.

  • 🇦🇺Australia kim.pepper 🏄‍♂️🇦🇺Sydney, Australia

    This might be better as a separate controller?

Production build 0.69.0 2024