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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.09 18:57:01