vue传formdata数据(vue formatter data参数)

一、需求背景

要求普通form数据和文件数据同时在一个接口传入后台进行保存

二、前端技术

使用vue+elemet ui+axios上传数据,通过Content-Type=multipart/form-data

三、开发步骤

1、新建一个vue页面

<el-form label-width="80px"
             :model="edit.form"
             ref="formData"
             size="mini">
        <input type="hidden" v-model="edit.form.pkid"/>
        <el-form-item label="类别"
                      key="controller_type">
            <el-select v-model="edit.form.controller_type"
                       style="width: 100%;">
                <el-option :label="option.label"
                           :value="option.value"
                           v-for="option in edit.controllerTypes"
                           :key="option.value"></el-option>
            </el-select>
        </el-form-item>
        <el-form-item label="名称"
                      key="name">
            <el-input v-model="edit.form.name"></el-input>
        </el-form-item>
        <el-form-item label="文件1"
                      key="file1">
            <el-upload class="avatar-uploader zb-flex"
                       :show-file-list="false"
                       :auto-upload="false"
                       action=''
                       accept=".png"
                       :on-change="handleFile1Change">
                <el-button slot="trigger" size="small" type="primary">选取文件</el-button>

                <div class="zb-flex" style="align-items: center">
                    <div style="margin-left: 20px; margin-right: 5px;" v-text="edit.files.file1.name"></div>
                    <i class="el-icon-close" style="color: red; cursor: pointer;" v-if="edit.files.file1.name" @click="removeFile('file1')"></i>
                </div>
            </el-upload>
​        </el-form-item>
​        <el-form-item label="文件2"
​                      key="file2">
​            <el-upload class="avatar-uploader zb-flex"
​                       :show-file-list="false"
​                       :auto-upload="false"
​                       action=''
​                       accept=".pdf"
​                       :on-change="handleFile2Change">
​                <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
                <div class="zb-flex" style="align-items: center">
                    <div style="margin-left: 20px; margin-right: 5px;" v-text="edit.files.file2.name"></div>
                    <i class="el-icon-close" style="color: red; cursor: pointer;" v-if="edit.files.file2.name" @click="removeFile('file2')"></i>
                </div>
​            </el-upload>
​        </el-form-item>
​        <el-form-item label="文件3"
​                      key="file3">
​            <el-upload class="avatar-uploader zb-flex"
​                       :show-file-list="false"
​                       :auto-upload="false"
​                       action=''
​                       accept=".txt"
​                       :on-change="handleFile3Change">
​                <el-button slot="trigger" size="small" type="primary">选取文件</el-button>
			</el-upload>
    </el-form-item>
</el-form>
<div>
    <el-button type="primary" @click="submit">提交</el-button>
</div>

可以看到建立了一个Form表单,添加6个栏位信息,其中三个是文件选择,因为是要上传三个不同类型的文件,所以添加了三个文件选择控件,用于上传不同的文件,这里在upload控件中有一个on-change事件,这个是在文件被选择后把对应的的文件信息保存到定义的变量中

2、显示页面

vue传formdata数据(vue formdata格式传递参数)vue传formdata数据(vue formdata格式传递参数)

3、编写JS上传代码

//文件1选择事件
handleFile1Change: function (file) {
     this.edit.files.file1 = file;
}

//文件2选择事件
handleFile2Change: function (file) {
     this.edit.files.file2 = file;
}

//文件3选择事件
handleFile3Change: function (file) {
		this.edit.files.file3 = file;
}

function async submit(){		
	let param = new FormData();
    param.append('pkid', this.edit.form.pkid);
    param.append('name', this.edit.form.name);
    param.append('controller_type', this.edit.form.controller_type);
   	param.append('files', this.edit.files.file1.raw);//添加文件1
    param.append('files', this.edit.files.file2.raw);//添加文件2
    param.append('files', this.edit.files.file3.raw);//添加文件3
    
    await axios({
    	url: option.url
        , method: 'post'
        , data: option.param
        , headers: {
        	'Content-Type': 'multipart/form-data'
        }
        , transformRequest: null //此处是为了避开请求拦截,如果没有设置全局请求拦截,则不用添加
    }).then(function (response) {
        console.log(response.data);
    }).catch(function (error) {
        console.log(error);
    });
}

注意事项:如果axios设置了全局请求拦截,则要设定transformRequest为null,以避过全局拦截导致的浏览器给Content-Type自动加的boundary被取消,而导致后台接收数据异常

四、问题解析

1、Missing content-type boundary

这个是因为用把Content-Type设置成multipart/form-data后,没有设置boundary数据分割符导致的

2、Unexpected end of Stream, the content may have already been read by another component

这是因为手动设置了boundary值导致服务器解析失败,所以要让浏览器自动添加boundary