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>