如何使用 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>