Laravel 9 + Vue.js 表单图片上传CRUD功能实现咨询
图片CRUD功能实现全方案
下面一步步搞定图片的CRUD,从数据库到前后端全流程调整:
一、先修正现有代码的明显错误
你给的表单里有个重复的nomor字段(文件类型的那个name也是nomor),先改成image,避免字段冲突。
二、数据库与Model配置
- 给你的表单数据表新增一个
image_path字段,类型用varchar(255),用来存储图片的访问路径。 - 修改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
相关产品推荐
相关产品推荐

