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

Laravel 9 + Vue.js 表单图片上传CRUD功能实现咨询

图片CRUD功能实现全方案

下面一步步搞定图片的CRUD,从数据库到前后端全流程调整:


一、先修正现有代码的明显错误

你给的表单里有个重复的nomor字段(文件类型的那个name也是nomor),先改成image,避免字段冲突。


二、数据库与Model配置

  1. 给你的表单数据表新增一个image_path字段,类型用varchar(255),用来存储图片的访问路径。
  2. 修改Model的$fillable,把新增字段加进去:
protected $fillable= [
    'nama',
    'alamat',
    'nomor',
    'email',
    'image_path' // 新增图片路径字段
];

三、前端表单与脚本调整

1. 修正表单结构

表单必须加enctype="multipart/form-data"属性才能上传文件,同时调整图片字段的name和规则:

<Form @submit="saveData()" enctype="multipart/form-data">
    <div class="form-row form-section" id="formParent">
        <div class="col-12 mb-3">
            <!-- 原有文本字段保留不变 -->
            <Field name="nomor" type="text" class="form-control3" v-model="form.nomor" placeholder="Nomor Telfon" :rules="isRequired" />
            <br>
            <ErrorMessage name="nomor" />
            <br>
            <!-- 修改图片字段的name和提示 -->
            <Field name="image" type="file" class="form-control3" accept="image/*" :rules="isRequired" />
            <br>
            <ErrorMessage name="image" />
            <!-- 原有email字段保留不变 -->
        </div>
        <button class="btnSubmit" type="submit">Gabung Mitra</button>
    </div>
</Form>

accept="image/*"可以限制用户只能选择图片文件,避免上传其他类型。

2. 调整Axios提交逻辑

上传文件不能用普通JSON提交,得用FormData包装数据:

<script>
import axios from 'axios';
import { Form, Field, ErrorMessage} from 'vee-validate';

export default {
  components: {
    Form,
    Field,
    ErrorMessage
  },
  data() {
    return {
      form: {
        nama: '',
        alamat: '',
        nomor: '',
        email: '',
        image: null // 新增图片字段
      },
    };
  },
  
  methods: {
      // 原有验证方法保留不变
      isRequired(value){
          if (value && value.trim()){
              return true;
          }
          return 'This is required';
      },
      validateEmail(value) {
        if (!value) {
          return 'This field is required';
        }
        const regex = /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i;
        if (!regex.test(value)) {
          return 'This field must be a valid email';
        }
        return true;
      },
      saveData(){
          // 创建FormData对象包装表单数据
          const formData = new FormData();
          formData.append('nama', this.form.nama);
          formData.append('alamat', this.form.alamat);
          formData.append('nomor', this.form.nomor);
          formData.append('email', this.form.email);
          // 添加上传的图片文件
          if (this.form.image) {
              formData.append('image', this.form.image);
          }

          // 发送请求时要设置正确的请求头
          axios.post('/form/submit', formData, {
              headers: {
                  'Content-Type': 'multipart/form-data'
              }
          }).then(
              response => {
                  console.log(response);
                  this.$toast.success(`Data berhasil dikirim`,{
                    position: "bottom",
                  });
                  // 提交成功后重置表单
                  this.form = {
                      nama: '',
                      alamat: '',
                      nomor: '',
                      email: '',
                      image: null
                  };
              }
          ).catch(error => {
              console.log(error);
              this.$toast.error(`Terjadi kegagalan`,{
                    position: "bottom",
                  });
          })
      }
  }
};
</script>

四、后端控制器逻辑调整

1. Store方法(新增数据+图片上传)

// 记得引入Storage类
use Illuminate\Support\Facades\Storage;

public function store(Request $request)
{
    // 验证请求数据,包括图片的类型和大小限制
    $request->validate([
        'nama' => 'required|string',
        'alamat' => 'required|string',
        'nomor' => 'required|string',
        'email' => 'required|email',
        'image' => 'required|image|mimes:jpeg,png,jpg,gif|max:2048' // 限制2MB以内的图片
    ]);

    $data = $request->only(['nama', 'alamat', 'nomor', 'email']);

    // 处理图片上传
    if ($request->hasFile('image')) {
        // 生成唯一文件名,防止重名覆盖
        $fileName = time() . '_' . $request->image->getClientOriginalName();
        // 保存到storage/app/public/images目录,执行php artisan storage:link创建软链接后才能前端访问
        $filePath = $request->image->storeAs('public/images', $fileName);
        // 把存储路径转换成前端可访问的storage路径
        $data['image_path'] = str_replace('public/', 'storage/', $filePath);
    }

    $response = Form::create($data);
    return response()->json([
        'status' => 'success',
        'data' => $response
    ], 200);
}

执行php artisan storage:link可以让public目录下的storage软链接指向storage/app/public,这样前端能通过asset($form->image_path)访问图片。

2. Update方法(修改数据+替换图片)

如果需要支持修改图片,要同时删除旧图片:

public function update(Request $request, $id)
{
    $form = Form::findOrFail($id);

    $request->validate([
        'nama' => 'required|string',
        'alamat' => 'required|string',
        'nomor' => 'required|string',
        'email' => 'required|email',
        'image' => 'nullable|image|mimes:jpeg,png,jpg,gif|max:2048' // 修改时图片可选
    ]);

    $data = $request->only(['nama', 'alamat', 'nomor', 'email']);

    // 如果上传了新图片,删除旧图片并保存新的
    if ($request->hasFile('image')) {
        if ($form->image_path) {
            $oldFilePath = str_replace('storage/', 'public/', $form->image_path);
            Storage::delete($oldFilePath);
        }
        $fileName = time() . '_' . $request->image->getClientOriginalName();
        $filePath = $request->image->storeAs('public/images', $fileName);
        $data['image_path'] = str_replace('public/', 'storage/', $filePath);
    }

    $form->update($data);
    return response()->json([
        'status' => 'success',
        'data' => $form
    ], 200);
}

3. Destroy方法(删除数据+删除图片)

删除数据时要同时删掉对应的图片文件:

public function destroy($id)
{
    $form = Form::findOrFail($id);

    // 删除图片文件
    if ($form->image_path) {
        $filePath = str_replace('storage/', 'public/', $form->image_path);
        Storage::delete($filePath);
    }

    $form->delete();
    return response()->json([
        'status' => 'success',
        'message' => 'Data deleted successfully'
    ], 200);
}

五、前端显示图片

获取数据后,用以下方式展示图片:

<!-- 假设formData是从后端获取的单条数据 -->
<img :src="`/${formData.image_path}`" alt="Profile Image" class="img-fluid">

或者用Laravel的asset辅助函数(如果是blade模板的话):

<img src="{{ asset($form->image_path) }}" alt="Profile Image" class="img-fluid">

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 13:01:12