如何使用 Javascript 中的提取 API 将文件上传到 Laravel 控制器?
How to upload a file using the fetch API in Javascript to a Laravel Controller?
我有一个 FILES
变量,如下所示:
我正在尝试在我的 Laravel 控制器上接收这些文件,如下所示:
if(!empty($request->allFiles()))
...
var_dump($request->all()); # debug
我正在使用 fetch
API 发布到此端点,如下所示:
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,
})
在我的回复(网络选项卡)中,我得到:
array(1) { ["files"]=> array(1) { [0]=> string(15) "[object Object]" } }
我尝试 JSON.Stringify(FILES)
并得到:
array(1) { ["files"]=> array(1) { [0]=> string(70) "{"blob:http://127.0.0.1:8000/502cbd0f-f2b7-4155-8475-d83e48bb9730":{}}" } }
任何人都可以指出正确的方向来说明为什么文件没有发布吗?这就是 FILES
的创建方式。
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;
}
您需要将 files 附加到您的 FormData 对象,而不是普通对象。
即给定 formData.append("key", value)
,该值需要是一个文件对象(它也可以是一个字符串)。它不能是 plain 对象(如示例中的 FILES
),因为它将被转换为字符串,这没有用:
const object = {};
console.log(object.toString());
从文件输入中手动提取文件并逐个附加它们过于复杂。通常,您只使用表单而不是附加到 FormData 对象:
<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>
我有一个 FILES
变量,如下所示:
我正在尝试在我的 Laravel 控制器上接收这些文件,如下所示:
if(!empty($request->allFiles()))
...
var_dump($request->all()); # debug
我正在使用 fetch
API 发布到此端点,如下所示:
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,
})
在我的回复(网络选项卡)中,我得到:
array(1) { ["files"]=> array(1) { [0]=> string(15) "[object Object]" } }
我尝试 JSON.Stringify(FILES)
并得到:
array(1) { ["files"]=> array(1) { [0]=> string(70) "{"blob:http://127.0.0.1:8000/502cbd0f-f2b7-4155-8475-d83e48bb9730":{}}" } }
任何人都可以指出正确的方向来说明为什么文件没有发布吗?这就是 FILES
的创建方式。
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;
}
您需要将 files 附加到您的 FormData 对象,而不是普通对象。
即给定 formData.append("key", value)
,该值需要是一个文件对象(它也可以是一个字符串)。它不能是 plain 对象(如示例中的 FILES
),因为它将被转换为字符串,这没有用:
const object = {};
console.log(object.toString());
从文件输入中手动提取文件并逐个附加它们过于复杂。通常,您只使用表单而不是附加到 FormData 对象:
<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>