I have a FILES
variable that looks like this:
I am trying to receive these files at my Laravel controller like so:
if(!empty($request->allFiles())) ... var_dump($request->all()); # debug
I am posting to this endpoint using the fetch
API like so:
let fd = new FormData(); fd.append('files[]', FILES) fetch('{{ url()->to(route('gallery.upload')) }}', { method: 'POST', credentials: "same-origin", headers: { "X-CSRF-Token": '{{ csrf_token() }}' }, body: fd, })
In my response (network tab) I get:
array(1) { ["files"]=> array(1) { [0]=> string(15) "[object Object]" } }
I tried to JSON.Stringify(FILES)
and got:
array(1) { ["files"]=> array(1) { [0]=> string(70) "{"blob:http://127.0.0.1:8000/502cbd0f-f2b7-4155-8475-d83e48bb9730":{}}" } }
Can anyone point me in the right direction to why the file is not posted? This is how the FILES
is created.
const fileTempl = document.getElementById("file-template"), imageTempl = document.getElementById("image-template"), empty = document.getElementById("empty"); let FILES = {}; function addFile(target, file) { const isImage = file.type.match("image.*"), objectURL = URL.createObjectURL(file); const clone = isImage ? imageTempl.content.cloneNode(true) : fileTempl.content.cloneNode(true); // Creates nice output of the file clone.querySelector("h1").textContent = file.name; clone.querySelector("li").id = objectURL; clone.querySelector(".delete").dataset.target = objectURL; clone.querySelector(".size").textContent = file.size > 1024 ? file.size > 1048576 ? Math.round(file.size / 1048576) + "mb" : Math.round(file.size / 1024) + "kb" : file.size + "b"; isImage && Object.assign(clone.querySelector("img"), { src: objectURL, alt: file.name }); empty.classList.add("hidden"); target.prepend(clone); FILES[objectURL] = file; }
Advertisement
Answer
You need to append files to your FormData object, not a plain object.
i.e. given formData.append("key", value)
, the value needs to be a file object (it can also be a string). It can’t be a plain object (like FILES
in your example) as that will be converted to a string, which isn’t useful:
const object = {}; console.log(object.toString());
Manually extracting the files from a file input and appending them one-by-one is overly complex though. Typically you would just use a form instead of appending to the FormData object:
<form action="example" method="POST" enctype="multipart/form-data"> <input type="file" name="files[]" multiple> <button>Submit</button> </form> <script> const form = document.querySelector('form'); form.addEventListener('submit', event => { const data = new FormData(form); fetch('url', { method: 'POST', body: new FormData(form); }); }); </script>