Laravel Vue 多张图片上传失败,每个图片都有一个 NULL 值

Posted

技术标签:

【中文标题】Laravel Vue 多张图片上传失败,每个图片都有一个 NULL 值【英文标题】:Laravel Vue Multiple image Upload failing on for each with a NULL value 【发布时间】:2020-12-27 09:44:08 【问题描述】:

我正在尝试在 Laravel 中上传多张图片,但是,一是无法在 html 附带的上传对话框中上传多个图片,二是在 foreach 之前的转储和死机测试中,我得到一个 NULL价值。我是 Laravel 和 vue 的新手,所以我确信这是一个简单的问题,但对于我的生活,我不知道我错过了什么。首先,我在 web.php 文件中运行 post 请求,我不确定这是否是一个好主意。无论如何,我的脚本在我上传文件之前就失败了。 这是我到目前为止的代码。

web.php

Route::post('/upload', function (Request $request) 
    $uploadedFiles = $request->pics;


    foreach ($uploadedFiles as $file) 
        dd($file);

        $file->store('dummy');
    

    return response(['status' => 'success'], 200);
);

app.js(没有我觉得无关紧要的代码)

require("./bootstrap");
window.Vue = require("vue");

import  Form, HasError, AlertError  from "vform";

window.Form = Form;

Vue.component(HasError.name, HasError);
Vue.component(AlertError.name, AlertError);

import VueRouter from "vue-router";
Vue.use(VueRouter);

let routes = [
    
        path: "/dashboard",
        component: require("./components/Dashboard.vue").default
    ,
    
    
    
        path: "/users",
        component: require("./components/Users.vue").default
    ,
    
        path: "/tasks",
        component: require("./components/Tasks.vue").default
    
];

const router = new VueRouter(
    mode: "history",
    routes
);

Vue.component(
    "dashboard-component",
    require("./components/Dashboard.vue").default
);

Vue.component("file-upload", require("./components/FileUpload.vue").default);


const app = new Vue(
    el: "#app",
    router
);

文件上传.vue

<template>
    <div>
        <input class="" type="file" @change="fieldChange" />
        <button class="btn btn-success float-right mt-3" @click="uploadFile">
            Upload
        </button>
    </div>
</template>

<script>
export default 
    data() 
        return 
            attachments: [],
            formImage: new FormData()
        ;
    ,
    methods: 
        fieldChange(e) 
            e.preventDefault();

            let selectedFiles = e.target.files;

            if (!selectedFiles.length) 
                return false;
            

            for (let i = 0; i < selectedFiles.length; i++) 
                this.attachments.push(selectedFiles[i]);
            
            console.log(this.attachments);
        ,
        uploadFile() 
            this.formImage.append("task_image", this.attachments);

            const config = 
                headers:  "Content-Type": "multipart/form-data" 
            ;

            axios
                .post("/upload", this.formImage, config)
                .then(response => 
                    // success
                )
                .catch(response => 
                    // fail
                );
        
    ,
    mounted() 
        console.log("Component mounted.");
    
;
</script>

Task.vue(完整的。我不知道这里是否有什么东西导致了冲突,所以我包括了所有内容)。

<template>
    <div class="custom-container">
        <div class="row justify-content-center">
            <div class="col-md-12">
                <div class="card">
                    <div
                        class="card-header text-white"
                        style="background-color: #605ca8;"
                    >
                        <h3 class="card-title">Tasks</h3>

                        <div class="card-tools">
                            <button class="btn btn-success" @click="newModal">
                                <i class="fas fa-tasks"></i> Add New Task
                            </button>
                            <!-- <div class="input-group input-group-sm" style="width: 150px;">
                <div class="input-group-append"></div>
              </div>-->
                        </div>
                    </div>
                    <!-- /.card-header -->
                    <div
                        class="table-x-y card-body table-responsive p-0"
                        style="max-height: 600px;"
                    >
                        <table class="table table-hover text-wrap">
                            <thead>
                                <tr>
                                    <th>Task</th>
                                    <th>Priority</th>
                                    <th>Assigned To</th>
                                    <th>Assigned By</th>
                                    <th>Date Assigned</th>
                                    <th>Due By:</th>
                                    <th>Task Desc.</th>
                                    <th>Images</th>
                                    <!-- <th>Notes</th> -->
                                    <th>finished</th>
                                    <th>Status</th>
                                    <th>Action</th>
                                </tr>
                            </thead>
                            <tbody>
                                <tr v-for="task in tasks" :key="task.id">
                                    <td> task.task_name </td>
                                    <td> task.task_priority </td>
                                    <td> task.task_assigned_to </td>
                                    <td> task.task_assigned_by </td>
                                    <td> task.created_at </td>
                                    <td>
                                         task.task_to_be_completed_date 
                                    </td>
                                    <td
                                        style="min-width: 300px; max-width: 301px;"
                                    >
                                         task.task_description 
                                    </td>
                                    <td>
                                        <img
                                            style="max-width: 150px;"
                                            src="/img/molding.jpg"
                                            alt
                                        />
                                         task.task_image 
                                    </td>
                                    <!-- <td> task.task_notes </td> -->
                                    <td> task.task_finished </td>
                                    <td> task.task_status </td>
                                    <td>
                                        <a
                                            href="#"
                                            class="badge badge-primary p-2 mb-3"
                                            @click="editModal(task)"
                                        >
                                            <i class="fa fa-edit"></i> Edit
                                        </a>
                                        <a
                                            @click="deleteTask(task.id)"
                                            href="#"
                                            class="badge badge-danger p-2"
                                        >
                                            <i class="fa fa-trash"></i> Delete
                                        </a>
                                        <file-upload></file-upload>
                                    </td>
                                </tr>
                            </tbody>
                        </table>
                    </div>
                    <!-- /.card-body -->
                </div>
            </div>
        </div>

        <form @submit.prevent="editmode ? updateTask() : createTask()">
            <!-- Modal -->
            <div
                class="modal fade"
                id="addNew"
                tabindex="-1"
                aria-labelledby="addNewLabel"
                aria-hidden="true"
            >
                <div class="modal-dialog modal-dialog-centered">
                    <div class="modal-content">
                        <div class="modal-header">
                            <h5
                                class="modal-title"
                                v-show="!editmode"
                                id="addNewLabel"
                            >
                                Add New Task
                            </h5>
                            <h5
                                class="modal-title"
                                v-show="editmode"
                                id="addNewLabel"
                            >
                                Update Task Information
                            </h5>

                            <button
                                type="button"
                                class="close"
                                data-dismiss="modal"
                                aria-label="Close"
                            >
                                <span aria-hidden="true">&times;</span>
                            </button>
                        </div>

                        <div class="modal-body">
                            <div class="form-group">
                                <input
                                    id="task_name"
                                    type="text"
                                    v-model="form.task_name"
                                    name="task_name"
                                    class="form-control"
                                    placeholder="Task Name"
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_name'
                                        )
                                    "
                                />
                                <has-error
                                    :form="form"
                                    field="task_name"
                                ></has-error>
                            </div>
                            <div class="form-group">
                                <select
                                    id="task_priority"
                                    type="text"
                                    v-model="form.task_priority"
                                    name="task_priority"
                                    class="form-control"
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_priority'
                                        )
                                    "
                                >
                                    <option value
                                        >Select a Priority Level</option
                                    >
                                    <option value="1">1</option>
                                    <option value="2">2</option>
                                    <option value="3">3</option>
                                    <option value="4">4</option>
                                    <option value="5">5</option>
                                </select>
                                <has-error
                                    :form="form"
                                    field="task_priority"
                                ></has-error>
                            </div>
                            <div class="form-group">
                                <input
                                    id="task_description"
                                    type="text"
                                    v-model="form.task_description"
                                    name="task_description"
                                    class="form-control"
                                    placeholder="Task Description"
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_description'
                                        )
                                    "
                                />
                                <has-error
                                    :form="form"
                                    field="task_description"
                                ></has-error>
                            </div>

                            <div class="form-group">
                                <input
                                    id="task_assigned_by"
                                    type="text"
                                    v-model="form.task_assigned_by"
                                    name="task_assigned_by"
                                    class="form-control"
                                    placeholder="Assigned By"
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_assigned_by'
                                        )
                                    "
                                />
                                <has-error
                                    :form="form"
                                    field="task_assigned_by"
                                ></has-error>
                            </div>
                            <div class="form-group">
                                <input
                                    id="task_assigned_to"
                                    type="text"
                                    v-model="form.task_assigned_to"
                                    name="task_assigned_to"
                                    class="form-control"
                                    placeholder="Assigned To"
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_assigned_to'
                                        )
                                    "
                                    value="form.user.id"
                                />
                                <has-error
                                    :form="form"
                                    field="task_assigned_to"
                                ></has-error>
                            </div>
                            <div class="form-group">
                                <label for="task_to_be_completed_date"
                                    >Due:</label
                                >
                                <input
                                    id="task_to_be_completed_date"
                                    type="date"
                                    v-model="form.task_to_be_completed_date"
                                    name="task_to_be_completed_date"
                                    class="form-control"
                                    placeholder="Due: "
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_to_be_completed_date'
                                        )
                                    "
                                />
                                <has-error
                                    :form="form"
                                    field="task_to_be_completed_date"
                                ></has-error>
                            </div>
                            <div class="form-group">
                                <select
                                    id="task_status"
                                    type="text"
                                    v-model="form.task_status"
                                    name="task_status"
                                    class="form-control"
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_status'
                                        )
                                    "
                                >
                                    <option value>Select Task Status</option>
                                    <option value="Pending">Pending</option>
                                    <option value="Finished">Finished</option>
                                    <option value="Incomplete"
                                        >Incomplete</option
                                    >
                                </select>
                                <has-error
                                    :form="form"
                                    field="task_status"
                                ></has-error>
                            </div>
                            <!-- <div class="form-group">
                <input
                  id="task_notes"
                  type="text"
                  v-model="form.task_notes"
                  name="task_notes"
                  class="form-control"
                  placeholder="Notes"
                  :class="
                            'is-invalid': form.errors.has(
                            'task_notes')
                        "
                />
                <has-error :form="form" field="task_notes"></has-error>
              </div>-->
                            <div class="form-group">
                                <select
                                    id="task_finished"
                                    type="text"
                                    v-model="form.task_finished"
                                    name="task_finished"
                                    class="form-control"
                                    :class="
                                        'is-invalid': form.errors.has(
                                            'task_finished'
                                        )
                                    "
                                >
                                    <option value
                                        >Select finished status</option
                                    >
                                    <option value="1">Finished</option>
                                    <option value="0">Unfinished</option>
                                </select>
                                <has-error
                                    :form="form"
                                    field="task_status"
                                ></has-error>
                            </div>
                            <!-- <div class="form-group">
                <input id="upload-file" class="form-control" type="file" @change="fieldChange" />
                <button class="btn btn-success float-right mt-3" @click="uploadFile">Upload</button>
              </div>-->
                        </div>
                        <div class="modal-footer">
                            <button
                                type="button"
                                class="btn btn-primary"
                                data-dismiss="modal"
                            >
                                Close
                            </button>
                            <button
                                v-show="editmode"
                                type="submit"
                                class="btn btn-success"
                            >
                                Update
                            </button>
                            <button
                                v-show="!editmode"
                                type="submit"
                                class="btn btn-primary"
                            >
                                Create New Task
                            </button>
                        </div>
                    </div>
                </div>
            </div>
        </form>
    </div>
</template>

<script>
export default 
    data() 
        return 
            editmode: true,
            tasks: ,
            attachments: [],
            formImage: new FormData(),
            form: new Form(
                id: "",
                task_name: "",
                task_description: "",
                task_assigned_by: "",
                task_assigned_to: "",
                task_to_be_completed_date: "",
                task_priority: "",
                // task_notes: "",
                task_status: "",
                task_finished: ""
                // task_image: "",
            )
        ;
    ,
    methods: 
        updateTask() 
            this.$Progress.start();
            this.form
                .put("api/task/" + this.form.id)
                .then(() => 
                    // successfull
                    $("#addNew").modal("hide");
                    Swal.fire(
                        "Updated",
                        "Task information updated.",
                        "success"
                    );
                    this.$Progress.finish();
                    Fire_event.$emit("AfterCreate");
                )
                .catch(() => 
                    // Unsuccessfull
                    this.$Progress.fail();
                );
        ,
        editModal(task) 
            this.editmode = true;
            this.form.reset();
            $("#addNew").modal("show");
            this.form.fill(task);
        ,
        newModal() 
            this.editmode = false;
            this.form.reset();
            $("#addNew").modal("show");
        ,
        deleteTask(id) 
            Swal.fire(
                title: "Are you sure?",
                text: "You won't be able to revert this!",
                icon: "warning",
                showCancelButton: true,
                confirmButtonColor: "#3085d6",
                cancelButtonColor: "#d33",
                confirmButtonText: "Yes, delete it!"
            ).then(result => 
                // Send request to the server
                if (result.value) 
                    this.form
                        .delete("api/task/" + id)
                        .then(() => 
                            Swal.fire(
                                "Deleted!",
                                "Task has been deleted.",
                                "success"
                            );

                            Fire_event.$emit("AfterCreate");
                        )
                        .catch(() => 
                            Swal.fire(
                                "Failed",
                                "Something went wrong.",
                                "warning"
                            );
                        );
                
            );
        ,
        loadTasks() 
            axios.get("api/task").then(( data ) => (this.tasks = data.data));
        ,
        createTask() 
            this.$Progress.start();
            this.form
                .post("api/task")
                .then(() => 
                    Fire_event.$emit("AfterCreate");
                    $("#addNew").modal("hide");
                    toast.fire(
                        icon: "success",
                        title: "Task Created successfully"
                    );
                    this.$Progress.finish();
                    this.target.reset();
                )
                .catch(() => 
                    this.$Progress.fail();
                    //   toast.fire(
                    //     icon: "error",
                    //     title: "The Task was not created.",
                    //   );
                );
        
    ,
    created() 
        this.loadTasks();
        // setInterval(() => this.loadUsers(), 3000);
        Fire_event.$on("AfterCreate", () => 
            this.loadTasks();
        );
    ,
    mounted() 
        console.log("Component mounted.");
    
;
</script>

对此的任何帮助将不胜感激。我正在尝试在本地上传到我的 sql 服务器。在我的 .env 文件中,我指定了 FILESYSTEM_DRIVER=public 指向该文件中预先指定的 config/filesystem.php 公共路由。

【问题讨论】:

【参考方案1】:

这里有几个问题

    您正在阻止 &lt;input type="file"&gt; 上的 change 事件的默认事件操作。不要那样做。从您的fieldChange 方法中删除此行

    e.preventDefault()
    

    Content-type 请求的 multipart/form-data 标头还需要包含 mime-boundary 标记。这些是在使用 FormData 时由浏览器自动添加的,因此您不应手动设置它们。将您的 Axios 调用更改为

    axios.post("/upload", this.formImage) // no config required
    

    您正在将一组文件添加到您的FormData。这不是您添加多个文件的方式。相反,您必须多次调用append()。向 PHP 发布数组数据时,字段名称也应以[] 为后缀

    this.attachments.forEach(file => 
      this.formImage.append("task_image[]", file)
    )
    

    见https://www.php.net/manual/features.file-upload.multiple.php

    您的 PHP 代码应该在请求文件中寻找 task_image,而不是 pics

    $uploadedFiles = $request->file('task_image');
    // or maybe
    $uploadedFiles = $request->task_image;
    // I don't know Laravel and the docs are useless for multiple file uploads
    

【讨论】:

谢谢菲尔。我实施了建议的更改,但仍然收到“为 foreach() 提供的参数无效”错误。我被难住了。 我根本不了解 Laravel,所以也许你需要 $uploadedFiles = $request-&gt;task_image; 这有点帮助。错误改了哈哈哈。现在我得到:消息:“调用字符串上的成员函数 store()” 在我的 dd() 调用中,我得到了绿色的 object_file。 :)

以上是关于Laravel Vue 多张图片上传失败,每个图片都有一个 NULL 值的主要内容,如果未能解决你的问题,请参考以下文章

laravel 8中多张图片上传的问题

Laravel 5.8 多张图片上传

Laravel 5.2 中的多张图片上传

Laravel 4 上传 1 张图片并保存为多张 (3)

带删除和预览的多张图片上传 Laravel

Laravel 上传多张带有错误 idback 的图像:“idback 必须是文件类型:jpg、jpeg、png。”