如何使用Prisma ORM将数据缓冲区存入PostgreSQL的Oid字段
问题分析
报错的核心原因是:PostgreSQL的Oid类型并非直接存储二进制数据,而是一个整数型标识符,指向PostgreSQL系统表pg_largeobject中的大对象(Large Object)。而你直接传入Buffer(二进制数据),和Prisma生成的Int类型(对应Oid)不匹配,导致类型错误。
两种解决方案
方案一:继续使用Oid存储大对象
需要先将Buffer写入PostgreSQL大对象,获取对应的Oid值,再存入data字段。步骤如下:
- 安装PostgreSQL客户端库
npm install pg
- 修改服务端代码,结合
pg库操作大对象
import { Pool } from 'pg'; import { PrismaClient } from '@prisma/client'; import { Request, Response } from 'express'; const prisma = new PrismaClient(); // 复用Prisma的数据库连接配置 const pool = new Pool({ connectionString: process.env.DATABASE_URL, }); app.post("/img", async (req: Request | any, res: Response) => { const file = req.files.data; const pgClient = await pool.connect(); try { await pgClient.query('BEGIN'); // 1. 创建空的大对象,获取Oid const createRes = await pgClient.query('SELECT lo_create(0) AS oid'); const oid = createRes.rows[0].oid; // 2. 打开大对象并写入Buffer数据 const openRes = await pgClient.query('SELECT lo_open($1, $2) AS fd', [oid, 2032]); // 2032代表WRITE模式 const fd = openRes.rows[0].fd; await pgClient.query('SELECT lo_write($1, $2, $3)', [fd, file.data, file.data.length]); // 3. 关闭大对象并提交事务 await pgClient.query('SELECT lo_close($1)', [fd]); await pgClient.query('COMMIT'); // 4. 用Prisma写入Oid到数据库 const img = await prisma.image.create({ data: { name: file.name, image_type: file.mimetype, image_size: file.size, data: oid, // 传入整数型Oid }, }); res.send({ status: "success", data: img, }); } catch (error) { await pgClient.query('ROLLBACK'); console.error(error); res.status(500).send({ status: "error", message: "图片上传失败" }); } finally { pgClient.release(); } });
- 注意事项
- 删除
image记录时,需要手动调用lo_unlink(oid)删除对应的大对象,避免垃圾数据残留; - 大对象适合存储GB级别的超大文件,日常小文件推荐用方案二。
方案二:改用Bytea直接存储二进制数据
如果你的图片文件不大(通常<1GB),直接用PostgreSQL的bytea类型存储更简单:
- 修改数据库表字段类型
ALTER TABLE image ALTER COLUMN data TYPE bytea;
- 更新Prisma Model
model image { id String @id @db.Uuid @default(uuid()) data Bytes @db.Bytea // 替换原有的Int @db.Oid image_size BigInt image_type String? @db.VarChar(25) name String? @db.VarChar(30) client client[] }
- 同步Schema到数据库
npx prisma db push # 或使用迁移:npx prisma migrate dev
- 原服务端代码无需修改,直接运行即可(Prisma的
Bytes类型支持直接传入Buffer)
内容的提问来源于stack exchange,提问作者Vasu Subbannavar
相关产品推荐
相关产品推荐

