Prisma与Supabase多图上传问题:imageUrl类型不兼容报错排查
多图上传至Supabase后,Prisma写入数据库报imageUrl类型不兼容错误
问题描述
我有一个支持多图上传的Input组件,已成功将图片上传至Supabase存储,但尝试将图片URL写入Prisma数据库时失败,执行create操作时提示**"Types of property 'imageUrl' are incompatible"**类型不兼容错误。
相关代码
图片输入组件代码
<Input name="image" type="file" multiple={true} required />
服务端操作代码
export async function createDescription(formData: FormData) { const homeId = formData.get("homeId") as string; const photos = formData.getAll("image") as string[]; const photoNames = photos.map((_, index) => `blog-${Date.now()}-${index}`); const uploadPromises = photos.map((photo, index) => { return supabase.storage.from("images").upload(photoNames[index], photo, { contentType: "image/png", cacheControl: "2592000", }); }); const uploadResults = await Promise.all(uploadPromises); const errors = uploadResults.map((result) => result.error).filter(Boolean); if (errors.length > 0) { return { error: "Unable to upload one or more blog images to Storage." }; } const paths = uploadResults.map((result) => result.data?.path); const photoUrls = paths.map( (path) => `${process.env.SUPABASE_URL}/storage/v1/object/public/images/${path}`, ); const { data: imageData } = await supabase.from("blogs").update([ { homeId, photoUrls, }, ]); if (imageData === null) { return { error: "Unable to upload one or more blog images to Storage." }; } const imageFilesUrl = photoUrls.map((url) => ({ url })); const data = await prisma.home.update({ where: { id: homeId, }, data: { title, addedDescription: true, HomePhoto: { create: { imageUrl: imageFiles, }, }, }, }); return redirect(`/create/${homeId}/address`); }
Prisma模型代码
model User { id String @id @unique authId String @unique email String @unique firstName String lastName String profileImage String? Home Home[] } model Home { id String @id @default(uuid()) title String? description String? guests String? bedrooms String? bathrooms String? country String? price Int? categoryName String? addedCategory Boolean @default(false) addedDescription Boolean @default(false) addedLocation Boolean @default(false) createdAT DateTime @default(now()) User User? @relation(fields: [userId], references: [id]) userId String? HomePhoto Photo[] } model Photo { id String @id @default(uuid()) imageUrl String createdAt DateTime @default(now()) updatedAt DateTime @updatedAt Home Home @relation(fields: [homeId], references: [id]) homeId String }
错误原因及修复方案
1. File类型断言错误
formData.getAll("image")获取的是File对象数组,不是字符串数组,类型断言as string[]会导致后续上传逻辑异常,同时引发类型不匹配。
修复:
const photos = formData.getAll("image") as File[];
2. Prisma关联创建格式错误
- Home模型的
HomePhoto是Photo[]数组,创建关联时需要传入对象数组,而非单个对象。 - 代码中
imageFiles未定义,实际应该用photoUrls直接生成符合Photo模型的对象数组,且imageUrl需要是字符串,不是对象。
修复:
// 生成符合Photo模型的对象数组 const photoRecords = photoUrls.filter(url => url !== undefined).map(url => ({ imageUrl: url })); const data = await prisma.home.update({ where: { id: homeId, }, data: { title, addedDescription: true, // 传入数组创建多条Photo记录 HomePhoto: { create: photoRecords, }, }, });
3. 处理路径为null的情况
uploadResults.map((result) => result.data?.path)可能产生null值,生成URL时需要过滤,避免无效URL写入数据库:
修复:
const photoUrls = paths .filter(path => path !== undefined) // 过滤null/undefined路径 .map(path => `${process.env.SUPABASE_URL}/storage/v1/object/public/images/${path}`);
4. 清理冗余代码
代码中更新Supabase的blogs表属于冗余操作,和Prisma写入逻辑无关,可以直接删除:
// 删除这段冗余代码 const { data: imageData } = await supabase.from("blogs").update([ { homeId, photoUrls, }, ]); if (imageData === null) { return { error: "Unable to upload one or more blog images to Storage." }; }
修复后的完整服务端代码示例
export async function createDescription(formData: FormData) { const homeId = formData.get("homeId") as string; const photos = formData.getAll("image") as File[]; const title = formData.get("title") as string; // 补充原代码中未定义的title获取逻辑 const photoNames = photos.map((_, index) => `blog-${Date.now()}-${index}`); const uploadPromises = photos.map((photo, index) => { return supabase.storage.from("images").upload(photoNames[index], photo, { contentType: photo.type, // 用File本身的类型,而非硬编码png cacheControl: "2592000", }); }); const uploadResults = await Promise.all(uploadPromises); const errors = uploadResults.map((result) => result.error).filter(Boolean); if (errors.length > 0) { return { error: "部分图片上传至存储失败" }; } const paths = uploadResults.map((result) => result.data?.path); const photoUrls = paths .filter(path => path !== undefined) .map(path => `${process.env.SUPABASE_URL}/storage/v1/object/public/images/${path}`); const photoRecords = photoUrls.map(url => ({ imageUrl: url })); try { await prisma.home.update({ where: { id: homeId }, data: { title, addedDescription: true, HomePhoto: { create: photoRecords } } }); } catch (dbError) { console.error("数据库写入失败:", dbError); return { error: "图片信息写入数据库失败" }; } return redirect(`/create/${homeId}/address`); }
内容的提问来源于stack exchange,提问作者Refael
相关产品推荐
相关产品推荐

