Laravel+Vue+Inertia更新文章时图片上传失败求助
问题描述
我开发了一个带文章功能的Web应用,每篇文章对应一张图片。创建文章时上传图片功能正常,但更新文章时无法完成图片上传——目前仅尝试给无图片的已有文章添加图片,后续再处理已有图片的情况。
用dd($request)打印请求内容发现:仅修改标题、摘要或正文时请求正常;但尝试上传图片(或同时修改文本+上传图片)时,请求内容为null,无任何错误提示,图片也无法保存到数据库。已排查验证规则、图片格式、路由,未找到问题根源。
Vue页面代码
<template> <AppLayout> <div class="bg-base-200"> <h1 class="text-4xl p-4">Modifica articolo</h1> <form class="px-8 bg-base-200 pb-8" @submit.prevent="submit" enctype="multipart/form-data"> <div class="space-y-12"> <div class="border-b border-white/10 pb-12"> <div class="mt-10 grid grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6"> <div class="sm:col-span-4 grid sm:grid-cols-4 gap-4"> <div class="sm:col-span-3"> <label for="username" class="block text-sm font-medium leading-6 text-white">Titolo</label> <div class="mt-2"> <div class="flex rounded-md bg-white/5 ring-1 ring-inset ring-white/10 focus-within:ring-2 focus-within:ring-inset focus-within:ring-indigo-500"> <span class="flex select-none items-center pl-3 text-gray-500 sm:text-sm"> </span> <input v-model="form.title" type="text" class="flex-1 border-0 bg-transparent py-1.5 pl-1 text-white focus:ring-0 sm:text-sm sm:leading-6" /> </div> </div> </div> </div> <div class="col-span-full"> <label for="about" class="block text-sm font-medium leading-6 text-white">Estratto</label> <div class="mt-2"> <textarea v-model="form.extract" rows="3" class="block w-full rounded-md border-0 bg-white/5 py-1.5 text-white shadow-sm ring-1 ring-inset ring-white/10 focus:ring-2 focus:ring-inset focus:ring-indigo-500 sm:text-sm sm:leading-6" /> </div> </div> <div class="col-span-full"> <label for="article-body" class="block text-sm font-medium leading-6 text-white">Testo dell'articolo</label> <div class="mt-2 bg-white/5 rounded-md"> <QuillEditor toolbar="full" v-model:content="form.body" contentType="html" theme="snow" /> </div> </div> <div class="col-span-full"> <label for="cover-photo" class="block text-sm font-medium leading-6 text-white">Foto</label> <!-- Show Image if it exists --> <div v-if="form.media_file && form.media_file.filepath"> <img :src="'/storage/' + form.media_file.filepath" alt="Article Image" class="object-cover mb-10" /> <button @click="removeImage" class="text-red-500">X</button> </div> <!-- Show Upload Option if No Image --> <div v-else class="mt-2 flex justify-center rounded-lg border border-dashed border-white/25 px-6 py-10"> <div class="text-center"> <div class="mt-4 flex text-sm leading-6 text-gray-400"> <label for="file-upload" class="relative cursor-pointer rounded-md bg-gray-900 font-semibold text-white focus-within:outline-none focus-within:ring-2 focus-within:ring-indigo-600 focus-within:ring-offset-2 focus-within:ring-offset-gray-900 hover:text-indigo-500"> <span>Carica una foto</span> <input id="file-upload" name="media_file" type="file" class="sr-only" @change="form.media_file = $event.target.files[0]" /> </label> <p class="pl-1">oppure trascinala qui</p> </div> <p class="text-xs leading-5 text-gray-400">PNG, JPG, GIF up to 10MB</p> </div> </div> </div> </div> </div> </div> <div class="mt-6 flex items-center justify-between gap-x-6"> <button @click="destroy" type="button" class="btn btn-error">Cancella</button> <button @click="$inertia.visit(route('admin.dashboard'))" type="button" class="btn btn-secondary">Annulla</button> <button @click="submit" type="submit" :disabled="form.processing" class="btn btn-primary ">Salva</button> </div> </form> </div> </AppLayout> </template> <script setup> import AppLayout from '@/Layouts/AppLayout.vue'; import { useForm } from '@inertiajs/vue3'; const props = defineProps({ article: Object }) let form = useForm({ id: props.article.id, title: props.article.title, extract: props.article.extract, body: props.article.body, media_file: props.article.media ? props.article.media[0] : null }) const submit = () => { const formData = new FormData(); formData.append('title', form.title); formData.append('extract', form.extract); formData.append('body', form.body); // Make sure you're appending the actual file object if (form.media_file) { formData.append('media_file', form.media_file); } // Use the put method to send the FormData for updating. form.put(route('articles.update', {id: props.article.id}), { body: formData }); } const destroy = () =>{ form.delete(route('articles.destroy', {id: props.article.id})); } </script>
ArticleController的Update方法
public function update(Request $request, Article $article) { dd($request); $validatedData = $request->validate([ 'title' => 'nullable|string|max:255', 'extract' => 'nullable|string|max:1000', 'body' => 'nullable|string', 'media_file' => 'sometimes|file|mimes:jpg,jpeg,png,gif,webp,mp4,mp3,pdf|max:10240', ]); $article->update($validatedData); if ($request->hasFile('media_file')) { $file = $request->file('media_file'); $path = $file->store('media', 'public'); $media = new Media([ 'filepath' => $path, 'filetype' => $this->determineFileType($file->getClientMimeType()), 'filename' => $file->getClientOriginalName(), 'article_id' => $article->id, ]); $media->save(); $article->media()->attach($media); } //return redirect()->route('admin.dashboard'); }
补充说明
使用Route::resource管理路由,创建文章时图片存储功能正常。
内容的提问来源于stack exchange,提问作者Marco Rifo
相关产品推荐
相关产品推荐

