laravel - 使用 VueJs 和 Laravel 上传多个文件

标签 laravel vue.js vuejs2

我尝试执行单个发布请求来上传多个文件。现在我有一个适用于多个文件的功能方法。但我想要一个请求。

submitFile(){
    this.contract_file.forEach((file) =>{
        let formData = new FormData();
        formData.append('file', file.file);

        axios.post('contracts/uploadfile/' + this.id_contract,
            formData,
            {
            headers: {
                'Content-Type': 'multipart/form-data',
            }
        }
        ).then(function(){
            //
        })
        .catch(function(){
            //
        });
    })
},

    public function uploadFile(Request $request, Contract $contract)
    {
            $filename = $request->file('file')->getClientOriginalName();

            $path = $request->file('file')->store($contract->id,'uploads');
            $contractFile = new ContractFile();

            $contractFile->fill([
                'contract_id'   => $contract->id,
                'name'          => $filename,
                'path'          => $path,
            ])->save();
    }

更新: 这是我改变的,但是..

let formData = []
this.contract_file.forEach((file,index) =>{
    formData[index] = new FormData();
    formData[index].append('file', file.file);
})

foreach($request->file('file') as $file){
    //same code but I use  $fille

留言:

Missing boundary in multipart/form-data POST data in Unknown

更新2:

    <file-upload
    class="btn btn-primary"
    :multiple="true"
    :drop="true"
    :drop-directory="true"
    v-model="files"
    @input-filter="inputFilter"
    @input-file="inputFile"

    ref="upload">
    <i class="fa fa-plus"></i>
    Select files
    </file-upload>

最佳答案

我的答案没有经过适当的测试,因为我不得不调整我的代码。如果它不起作用或我遗漏了什么,请告诉我。

基本上,我构建了自己的 FormData 以使其更灵活且更易于重用。

Form.vue

<template>
<div>
    <input @change="upload($event)"
        type="file"
        name="picture"
        id="new-file"
        class="custom-file-input"
        aria-label="picture"
        multiple
        >
    <label class="custom-file-label" for="new-file">
        <span>File...</span>
        <span class="btn-primary">Browse</span>
    </label>
    <button @click="submit" type="button" >Submit</button>
</div>
<template>

<script>
    import MyFormData from "./MyFormData";

    export default {
        data() {
           return {
               form: new MyFormData({contract_id: 5, files: []})
           }
        },
        methods: {
            upload(event) {
                for (let file of event.target.files) {
                    try {
                        let reader = new FileReader();
                        reader.readAsDataURL(file); // Not sure if this will work in this context.
                        this.form.files.push(file);
                    } catch {}
                }
            },
            submit(){
                this.form.post('/my-url')
                    .catch(errors => {
                        throw errors;
                    })
                    .then((response) => location = response.data.redirect);
            }
        }
    }
</script>

MyFormData.js

export default class MyFormData {
    constructor(data, headers) {
        // Assign the keys with the current object MyFormData so we can access directly to the data: 
        // (new FormData({myvalue: "hello"})).myvalue; // returns 'hello'
        Object.assign(this, data);

        // Preserve the originalData to know which keys we have and/or reset the form
        this.originalData = JSON.parse(JSON.stringify(data));

        this.form = null;
        this.errors = {};
        this.submitted = false;
        this.headers = headers || {}
    }

    // https://stackoverflow.com/a/42483509/8068675
    // It will build a multi-dimensional Formdata
    buildFormData(data, parentKey) {
        if (data && typeof data === 'object' && !(data instanceof Date) && !(data instanceof File) && !(data instanceof Blob)) {
            Object.keys(data).forEach(key => {
                this.buildFormData(data[key], parentKey ? `${parentKey}[${key}]` : key);
            });
        } else {
            const value = data == null ? '' : data;
            this.form.append(parentKey, value);
        }
    }

    // Returns all the new / modified data from MyFormData
    data() {
        return Object.keys(this.originalData).reduce((data, attribute) => {
            data[attribute] = this[attribute];
            return data;
        }, {});
    }

    post(endpoint) {
        return this.submit(endpoint);
    }

    patch(endpoint) {
        return this.submit(endpoint, 'patch');
    }

    delete(endpoint) {
        return axios.delete(endpoint, {}, this.headers)
            .catch(this.onFail.bind(this))
            .then(this.onSuccess.bind(this));
    }

    submit(endpoint, requestType = 'post') {
        this.form = new FormData();
        this.form.append('_method', requestType);
        this.buildFormData(this.data());

        return axios.post(endpoint, this.form, {
            headers: {
                'Content-Type': `multipart/form-data; boundary=${this.form._boundary}`,
            }
        })
            .catch(this.onFail.bind(this))
            .then(this.onSuccess.bind(this));
    }

    onSuccess(response) {
        this.submitted = true;
        this.errors = {};

        return response;
    }

    onFail(error) {

        console.log(error);

        this.errors = error.response.data.errors;
        this.submitted = false;

        throw error;
    }

    reset() {
        Object.assign(this, this.originalData);
    }
}

编辑 根据您指定使用的说明 vue-upload-component

你的提交方法应该是这样的

submitFile(){

    let files = this.contract_file.map((obj) => obj.file));
    let form = new MyFormData({files: files});

    form.post('contracts/uploadfile/' + this.id_contract)
        .then(function(){
            //
        })
        .catch(function(){
            //
        });
},

在你的 Controller 中

public function uploadFile(Request $request, Contract $contract) {
    if($request->hasFile('files')){
        $files = $request->file('files');
        foreach ($files as $file) {
            $filename = $file->getClientOriginalName();
            $path = $file->store($contract->id,'uploads');

            $contractFile = new ContractFile();
            $contractFile->fill([
                'contract_id'   => $contract->id,
                'name'          => $filename,
                'path'          => $path,
            ])->save();
        }
    }
}

关于laravel - 使用 VueJs 和 Laravel 上传多个文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60187372/

相关文章:

vue.js - 在 q 表列中显示从字段而不是字段本身派生的值

php - 在扩展布局的 View 中无法访问 Laravel View Composer 变量

javascript - 在提交表单 Vue.js 时显示 Flash 消息

php - 查询范围如何在 Laravel 中工作?

vue.js - 向 Vue cli 3 添加 PostCSS 支持的正确方法

javascript - 动态 Div Id 从路线获取

javascript - 如何使用 JavaScript 检查客户端浏览器性能?

vue.js - 在提交时获取表单数据?

javascript - 如何在 chart.js 中从最高到最低对数据进行排序

php - Laravel:检测是否加载了嵌套关系