本文详细解析了在使用Element-UI的upload组件时,如何在上传文件的同时传递其他业务参数。通过对比URL传参、before-upload钩子及FormData构造三种方案,重点阐述了利用axios配合FormData对象解决Content-Type冲突及参数传递失败的具体代码实现与注意事项。
近期项目中使用了基于VueThink构建的应用,其中集成了Element-UI库。由于开发者此前主要使用Bootstrap框架,对JavaScript的理解尚不深入,且虽接触过Vue.js但掌握程度有限,因此在开发过程中遇到了诸多挑战。
下文将具体分析在使用Element-UI过程中遇到的关于文件上传的问题,并分享相应的解决思路,如有疏漏之处,欢迎指正。
首先,参考Element-UI官方文档中关于upload组件的基础介绍。
<el-upload
class="upload-demo"
action="https://jsonplaceholder.typicode.com/posts/"
:on-preview="handlePreview"
:on-remove="handleRemove"
:file-list="fileList">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>

本质上,该组件是对原生<input type="file">元素进行的样式封装。
一、action URL配置
初看action属性中的URL时存在疑惑,后端采用PHP语言开发。经过后续实践理解,该URL实际上对应PHP后端的处理接口,类似于HTML表单中的action属性。不同之处在于,经过多次尝试,未能找到修改默认POST提交方式的方法。
二、文件接收时同时传递其他参数
方案一:通过URL传参
尝试对PHP提供的URL进行参数拼接,这是最直观的思路。然而,由于action属性默认使用POST方式,而后端采用RESTful风格的URL设计,POST方式无法直接实现此类传参。尝试多种方法均未成功,且未找到改为GET方式的有效途径。
因此,第一种方案不可行,予以放弃。
方案二:绕过action属性
查阅相关资料后发现,可以不依赖action属性,转而利用before-upload属性。该属性是一个函数类型,默认接收当前文件对象作为参数。只要能在该函数中处理文件,即可实现上传效果。
为了实现这一功能,需要创建一个新的FormData对象,并向其中追加键值对,操作方式类似于Postman测试接口时的做法。

网上有类似示例,大致结构如下。
beforeUpload (file) {
let fd = new FormData()
fd.append('key', file, fileName)
axios.post(url, fd. {
//做一些操作
})
return false // false就是不自动上传,我后来试了发现都一样,都不会自动上传
},
基于此思路,尝试编写了如下代码实现。
beforeUpload (file,id) {
let fd = new FormData()
fd.append('key', file, fileName)
axios.post(url, fd. {
data:{
id:id
}
})
return false // false就是不自动上传,我后来试了发现都一样,都不会自动上传
},
但在实际测试中发现,无论怎样调整,只能成功传递id参数,而在PHP后端通过dump(_FILES)查看时始终为NULL。排查许久未果,随后注意到请求的Content-Type应为multipart/form-data,而通过f12调试页面显示为application/json; charset=utf-8,推测是类型不匹配导致的问题。于是尝试在代码中手动添加headers设置。
beforeUpload (file,id) {
let fd = new FormData()
fd.append('key', file, fileName)
axios.post(url, fd. {
data:{
id:id
},
headers: {
'Content-Type': 'multipart/form-data'
}
})
return false // false就是不自动上传,我后来试了发现都一样,都不会自动上传
},
此次报错提示axios Missing boundary in multipart/form-data,即缺少边界信息,令人困惑。
进一步研究发现,Content-Type通常由浏览器自动识别并添加边界信息。也有人建议将Content-Type设置为undefined以强制自动识别,但尝试后仍无效,系统依然自动识别Content-Type。
最终发现,传递FormData对象时不能同时传递data属性。若需传递FormData,则必须移除data参数,修改后的请求方式如下。
beforeUpload (file,id) {
let fd = new FormData()
fd.append('file', file)
fd.append('id',id)
axios.post(url, fd, {
})
return false // false就是不自动上传,我后来试了发现都一样,都不会自动上传
},
按照上述修改后,问题得以解决。
以下是具体的代码实现。
<el-upload class="upload-demo"
drag
action="123"
:before-upload="beforeUpload"
multiple
ref="newupload"
:auto-upload="false"
accept=".mp4,.flv,.mov"
:on-change="newhandleChange"
:on-success="newhandlesuccess">
<i class="el-icon-upload"></i>
<div class="el-upload__text">将文件拖到此处,或<em>点击上传</em> </div>
<div class="el-upload__tip" slot="tip">请注意您只能上传.mp4 .flv .mov格式的视频文件</div>
</el-upload>
el-button type="primary" @click="newSubmitForm()" class="yes-btn">
确 定
</el-button>
<el-button @click="resetForm('newform')">
重 置
</el-button>
beforeUpload (file) {
console.log(file)
let fd = new FormData()
fd.append('file', file)
fd.append('groupId', this.groupId)
// console.log(fd)
newVideo(fd).then(res => {
console.log(res)
})
return true
},
newSubmitForm () {
this.$refs.newupload.submit()
},
export function newVideo (data) {
return axios({
method: 'post',
url: 'http://localhost:8086/Platform1-back-end/public/admin/VideoBase/newVideo',
timeout: 20000,
data: data
})
}
我将axios请求封装在独立文件中,与Vue组件分离,这种架构方式与直接写在组件内效果相似。
另外,如果在action属性中随意填写非空字符串,可能会引发404错误,但这不影响最终的上传效果。若有洁癖,可研究如何消除这一报错。
方案三:分多次传值
由于方案二已成功解决问题,方案三未进行实际测试,且从便利性角度看,多次传值并无实际意义。
至此,关于Element-UI中upload组件如何同时传递文件及其他参数的内容介绍完毕。如需了解更多相关Element-UI upload组件的内容,请搜索本站历史文章或继续阅读后续相关文章,感谢大家的支持!