You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Alpine.js表单多文件上传问题:Laravel后端图片数组为空

问题:多文件上传表单Laravel后端接收不到图片数组

我用HTML表单+Alpine.js构建了带多文件上传的表单,后端采用Laravel处理。目前能正常接收firstname和secondname字段,但插入数据库时images数组始终为空,请问我是否正确获取了上传的图片?


HTML代码

<div class="row" x-data="pageState()" x-init="mounted()">
<form method="post" enctype="multipart/form-data" @submit.prevent="postFormData()">
<div class="col-sm-4 p-2"><label>First Name</label><input x-model="form.firstname" name="firstname" type="text" required  /></div>
<div class="col-sm-4 p-2"><label>Second Name</label><input x-model="form.secondname" name="secondname" type="text" required /></div>
<div class="col-sm-4 p-2"><label>Images</label><input  name="images" type="file" x-on:change="selectFile($event)" accept="image/png, image/jpg, image/jpeg" multiple required /></div>
<button class="btn btn-primary mt-5">Submit Form Data</button>
</form>
</div>

Alpine.js代码

function pageState(){
           return {
               form: {
                    firstname: '',
                    secondname: '',
                },

                selectFile(event) {
                this.form.images = event.target.files[0];
                 },
            

                postFormData(){
                  
                  //Create an instance of FormData
                const data = new FormData()
                let url = 'http://localhost:8000/alpine_form'
                
                // Append the form object data by mapping through them
                Object.keys(this.form).map((key, index) => {
                    data.append(key, this.form[key])
                });

                
                fetch(url, {
                        method: 'POST',
                        /**
                        headers: {
                            'Accept': 'application/json',
                            'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                        },
                        */
                        body: data
                    })
                    .then(response => {
                        console.log(response);
                    })
                    .finally(() => {
                        
                    });
                    
                    
                /**
                axios.post('https://eot1ip4i6xwine.m.pipedream.net', {
                    firstname: this.firstname,
                    secondname: this.secondname
                  })
                  .then(function (response) {
                    console.log(response);
                  })
                  .catch(function (error) {
                    console.log(error);
                  });
                  */
                },
                
                mounted(){
                this.$watch('form.firstname', (value, oldValue) => this.form.firstname = value);
                this.$watch('form.firstname', (value, oldValue) => console.log(value, oldValue));
                console.log('mounted');
                }
           }
       }

Laravel后端代码

public function alpine_form(Request $request){
        
        header('Access-Control-Allow-Origin: *');

        header('Access-Control-Allow-Methods: GET, POST');

        header("Access-Control-Allow-Headers: X-Requested-With");

        
        $data = $request->all();
        $firstname = $data['firstname'];
        $secondname = $data['secondname'];
        $images = $data['images'];
        $ai = '';
        
        $uploaded_images_array = [];
         
            //images
        
        if($request->hasfile('images'))
            {
        
            foreach($request->file('images') as $fil)
            {
                $nam = mt_rand().uniqid().'.'.$fil->extension();
                $fil->move(public_path().'/uploads/', $nam);  
                $uploaded_images_array[] = $nam;  
            }
            
        
        $ai = json_encode($uploaded_images_array);
    
            DB::table('form')->insert(
             array(
                    'firstname'     => $firstname, 
                    'secondname'   => $secondname,
                    'images'   =>  $ai
             )
        );
        
            }
            
        

    }

问题分析与修复方案

核心问题出在前端对多文件的处理逻辑上,具体修复点如下:

1. 修正多文件存储逻辑

你的selectFile方法只取了选中的第一个文件(event.target.files[0]),但文件输入开启了multiple属性,需要保存所有选中的文件:

selectFile(event) {
  this.form.images = Array.from(event.target.files);
}

2. 修正FormData追加多文件的方式

直接将数组通过data.append('images', this.form.images)无法正确传递多文件,需要循环每个文件,以同一个key多次追加:

postFormData(){
  const data = new FormData()
  let url = 'http://localhost:8000/alpine_form'

  // 追加普通文本字段
  data.append('firstname', this.form.firstname);
  data.append('secondname', this.form.secondname);

  // 循环追加多文件
  if (this.form.images) {
    this.form.images.forEach(file => {
      data.append('images[]', file);
    });
  }

  fetch(url, {
    method: 'POST',
    headers: {
      'X-CSRF-TOKEN': document.querySelector('meta[name="csrf-token"]').content
    },
    body: data
  })
  .then(response => {
    console.log(response);
  })
  .finally(() => {});
}

这里使用images[]是为了让Laravel能识别为数组,也可以直接用images,只要循环追加同一个key即可。

3. 恢复CSRF Token验证

Laravel默认要求POST请求携带CSRF Token,你之前注释掉了相关配置,需要恢复。注意不要手动设置Content-Type,浏览器会自动为FormData添加正确的multipart/form-data请求头。

后端优化(可选)

后端逻辑本身没有问题,但可以更简洁地获取字段:

public function alpine_form(Request $request){
    // 建议通过Laravel的CORS中间件处理跨域,而非手动设置header
    $firstname = $request->input('firstname');
    $secondname = $request->input('secondname');
    $uploaded_images_array = [];
    
    if($request->hasFile('images')){
        foreach($request->file('images') as $fil){
            $nam = mt_rand().uniqid().'.'.$fil->extension();
            $fil->move(public_path('uploads'), $nam);  
            $uploaded_images_array[] = $nam;  
        }
        
        DB::table('form')->insert([
            'firstname' => $firstname, 
            'secondname' => $secondname,
            'images' => json_encode($uploaded_images_array)
        ]);
    }
}

另外,跨域建议使用Laravel官方推荐的CORS中间件,而非手动设置header。


内容的提问来源于stack exchange,提问作者Gandalf

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.14 20:55:21