1

I'm trying to upload assets directly to a volume using the 'assets/upload' controller in a front-end form.

There must have been some changes since Craft 3 and I'm running into 2 issues:

  • Issue 1: Posting to assets/upload now returns a json response, resulting in a HTTP 400 – Bad Request – yii\web\BadRequestHttpException - Request must accept JSON in response. I've temporarely solved this by sending an Accept: application/json header but was wondering if there's a recommended way to do this?
  • Issue 2: I'm trying to upload multiple files, but only 1 file is uploaded. Multiple files are in the payload and there's no error. Is there anything I need to do to handle multiple file uploads?

Here's a stripped down version of my form.

<form method="post" accept-charset="UTF-8" enctype="multipart/form-data">
  {{ csrfInput() }}
  {{ actionInput('assets/upload') }}
  {{ hiddenInput('folderId', 18) }}

  <input name="assets-upload" type="file" multiple>

  <button type="submit">Upload files</button>
</form>

2 Answers 2

2

Issue 1: Posting to assets/upload now returns a json response, resulting in a HTTP 400 – Bad Request – yii\web\BadRequestHttpException - Request must accept JSON in response. I've temporarely solved this by sending an Accept: application/json header but was wondering if there's a recommended way to do this?

That is the recommended way. The controller action can only return JSON, so it requires the client to accept a JSON response. This is enforced in the controller action, and you can't change that.

Issue 2: I'm trying to upload multiple files, but only 1 file is uploaded. Multiple files are in the payload and there's no error. Is there anything I need to do to handle multiple file uploads?

The controller action doesn't support multiple uploads. In the source code for that action you can see that it is only looking for a single uploaded file, and the rest of the code only supports saving a single asset. You can't change that from the outside, but there are a couple of options on how to solve this issue:

  1. Intercept the form submission using JavaScript, then upload the files one-by-one using fetch() or something similar. There are some libraries that will help you do that, filepond for instance.
  2. Write your own controller with an action that supports multiple uploads in a single request. You can use the existing controller action as a template, and then extend that to support multiple uploads.
2
  • Thank you Moritz. As Craft itself is using this controller to upload files, I guess they also do something 'extra' in de control panel to process multiple files. Commented Oct 10, 2023 at 10:38
  • @MetaMachine Yes, they're using approach #1, intercepting the upload with JavaScript and then using one separate request for every file. If you open the Network tab in your Browser DevTools, then upload multiple assets at once, you can see that it fires one request to assets/upload for every individual file.
    – MoritzLost
    Commented Oct 10, 2023 at 10:59
-1

Regarding your issue 2, I think to upload multiple files you need to add brackets to the name like:

<input name="assets-upload[]" type="file" multiple>

Then use:

UploadedFile::getInstancesByName('assets-upload')

1
  • just want to clarify that "adding brackets" here means "treat the data as an array". When something is an array data type you need to treat it as such, which can help with issues like these throughout development :)
    – cherrykoda
    Commented Oct 16, 2023 at 20:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.