Laravel5.8获取Vue经Axios发送的FormData文件失败
问题根因
当前实现有3个核心错误,直接导致Laravel无法接收上传文件:
- 错误将FormData实例作为普通对象的属性赋值,axios序列化请求时会把嵌套的FormData解析为空值,不会正确读取内部存储的文件
- 提交时直接发送Vue data中定义的普通JSON对象,没有将所有业务字段挂载到顶层FormData实例中
- 未给axios配置
multipart/form-data请求头,请求默认以application/json格式发送,本身不支持文件传输
分步修复方案
1. 调整前端基础定义与文件选择逻辑
不要在文件选择回调中单独实例化FormData,提前修正data结构,文件选择后直接存储原始文件列表即可:
// Vue实例data定义 data() { return { form: { discount_amount: '', student_id: '', batch_id: '', batch_fee: '', attachments: null, selected_bill_months: [] } } }, methods: { // 文件选择回调 setFile(e) { // 直接存储选中的文件列表,不要提前封装FormData this.form.attachments = e.target.files },
注意:文件上传input标签必须加multiple属性,支持多文件选择
2. 修正表单提交逻辑
提交时统一实例化顶层FormData对象,将所有业务字段、数组值、文件逐个追加到FormData中,配置正确请求头后再发送请求:
async submitForm() { // 补全业务字段 this.form.student_id = this.currentStudent.id this.form.batch_id = this.currentBatch.id this.form.batch_fee = this.currentBatch.fee // 实例化顶层FormData,所有提交字段都直接挂载到该实例 const submitData = new FormData() // 追加普通单值字段 submitData.append('discount_amount', this.form.discount_amount) submitData.append('student_id', this.form.student_id) submitData.append('batch_id', this.form.batch_id) submitData.append('batch_fee', this.form.batch_fee) // 追加多选账单月份,数组类型字段key必须加[]后缀,Laravel才能正确识别为数组 this.form.selected_bill_months.forEach(month => { submitData.append('selected_bill_months[]', month) }) // 追加多文件,同样使用带[]后缀的key if (this.form.attachments) { for (let i = 0; i < this.form.attachments.length; i++) { submitData.append('attachments[]', this.form.attachments[i]) } } // 发送请求,必须配置multipart/form-data请求头 const res = await axios.post('/university/api/discounts', submitData, { headers: { 'Content-Type': 'multipart/form-data' } }) console.log(res.data) }
3. Laravel后端接收逻辑
修复前端后,后端可直接通过请求实例获取文件和字段,参考验证逻辑如下:
public function store(Request $request) { // 调试时可打开下面注释查看所有提交字段 // dd($request->all()); $validated = $request->validate([ 'discount_amount' => 'required|numeric', 'student_id' => 'required|exists:students,id', 'batch_id' => 'required|exists:batches,id', 'batch_fee' => 'required|numeric', 'selected_bill_months' => 'required|array', 'attachments' => 'required|array', 'attachments.*' => 'file|max:10240|mimes:pdf,jpg,png,doc,docx' // 单文件校验规则 ]); // 后续业务逻辑:通过$request->file('attachments')即可拿到所有上传的文件实例 }
避坑提醒
- 所有数组类型的提交字段(多文件、多选值),FormData对应的key必须加
[]后缀,否则Laravel只能接收到最后一个值,甚至识别为空 - 禁止将FormData实例嵌套在普通JSON对象中传递,必须直接将顶层FormData实例作为axios的请求体参数
- 如果项目配置了axios全局拦截器,需要检查是否存在强制把请求体序列化为JSON的逻辑,发送multipart请求时要跳过该序列化逻辑
- 若使用
PUT/PATCH路由提交文件,Laravel需要额外在FormData中追加_method字段对应请求方法,同时axios统一用post发送,避免部分浏览器不支持put请求传文件的问题
内容的提问来源于stack exchange,提问作者Abdul Raheem Ghani
相关产品推荐
相关产品推荐

