Laravel+Inertia+React图书CRUD更新时图片无法读取问题
问题概述
搭建CRUD数据更新系统时,文本类数据可正常更新,但图片数据无法传递到Laravel后端,两种传参方式均出现异常:
- 直接传递Blob时,后端接收的
image字段为null - 使用FormData转普通对象传递时,后端接收的请求数据为空数组
相关代码与现象
1. Laravel控制器代码
public function update_book(Request $request, $id) { // dd($request->all()); $book = Book::find($id); $imageName = $request->file('image')->store('public/book'); $book->update([ 'name' => $request->name, 'date' => $request->date, 'author' => $request->author, 'stock' => $request->stock, 'description' => $request->description, 'image' => $imageName ]); $book->categories()->sync($request->categories); return redirect()->route('admin.books_panel')->with('success', 'Data Successfully Updated!'); }
2. 直接传Blob的React代码
const [image, setImage] = useState<File | null>(null) const handleImageChange = (e: React.ChangeEvent<HTMLInputElement>) => { if (e.target.files && e.target.files[0]) { setImage(e.target.files[0]) } } const updateBook = async (e: FormEvent<HTMLFormElement>) => { e.preventDefault() let cat: string[] = [] selectedCategories.forEach(categoryId => { cat.push(categoryId) }) Inertia.put(`/admin/books-panel/${book.id}`, { name: name, date: date, author: author, stock: stock, description: description, image: image as Blob, categories: cat.slice(1) }) }
后端打印结果:
array:7 [▼ // app\Http\Controllers\AdminController.php:114 "name" => "ddd" "date" => "2024-03-05" "author" => "ccc" "stock" => 1111 "description" => "ccc" "image" => null "categories" => array:2 [▶] ]
3. FormData转普通对象的React代码
const updateBook = async (e: FormEvent<HTMLFormElement>) => { e.preventDefault() const formData = new FormData() formData.append('name', name) formData.append('date', date) formData.append('author', author) formData.append('stock', stock) formData.append('description', description) if (image !== null) { const imageFile = new File([image], 'image.jpg') formData.append('image', imageFile) } selectedCategories.forEach(categoryId => { formData.append('categories[]', categoryId) }) const payload = Object.fromEntries(formData.entries()) console.log(payload) Inertia.put(`/admin/books-panel/${book.id}`, payload) }
前端控制台:payload包含完整数据
后端打印结果:[](空数组)
解决方法
问题核心是Inertia对文件上传的处理规范,需按以下步骤修改:
1. React端修改:直接传递FormData并设置请求头
Inertia支持直接上传FormData,无需转成普通对象,同时要显式设置请求头:
const updateBook = async (e: FormEvent<HTMLFormElement>) => { e.preventDefault() const formData = new FormData() formData.append('name', name) formData.append('date', date) formData.append('author', author) formData.append('stock', String(stock)) // 数字转字符串,避免FormData类型解析问题 formData.append('description', description) if (image !== null) { formData.append('image', image) // 直接使用选中的File对象,无需重新创建 } // 处理分类,直接append单个值,无需加[] selectedCategories.slice(1).forEach(categoryId => { formData.append('categories', categoryId) }) await Inertia.put(`/admin/books-panel/${book.id}`, formData, { headers: { 'Content-Type': 'multipart/form-data' } }) }
2. Laravel控制器修改:增加文件存在判断
避免用户未上传图片时抛出错误,同时优化数据更新逻辑:
public function update_book(Request $request, $id) { $book = Book::findOrFail($id); // 用findOrFail替代find,避免null报错 $updateData = [ 'name' => $request->name, 'date' => $request->date, 'author' => $request->author, 'stock' => $request->stock, 'description' => $request->description, ]; // 仅当有图片上传时处理存储 if ($request->hasFile('image')) { $imageName = $request->file('image')->store('public/book'); $updateData['image'] = $imageName; } $book->update($updateData); $book->categories()->sync($request->categories); return redirect()->route('admin.books_panel')->with('success', 'Data Successfully Updated!'); }
内容的提问来源于stack exchange,提问作者Maulana A
相关产品推荐
相关产品推荐

