TRPC返回图片数据报错求助:无法转换服务器响应
TRPC返回图片数据时出现「TRPCClientError: Unable to transform response from server」的解决方法
问题场景
作为TRPC新手,在开发包含产品图片的应用时,调用TRPC接口返回图片数据时触发错误:TRPCClientError: Unable to transform response from server,核心需求是实现TRPC正常返回并渲染图片数据。
相关代码参考
后端Prisma Product模型
model Product { id Int @id @default(autoincrement()) name String image Bytes? // 常见存储二进制图片的字段类型 createdAt DateTime @default(now()) }
后端TRPC Query接口
import { initTRPC } from '@trpc/server'; import { z } from 'zod'; import { prisma } from '../lib/prisma'; const t = initTRPC.create(); export const appRouter = t.router({ getProductById: t.procedure .input(z.number()) .query(async ({ input }) => { return await prisma.product.findUnique({ where: { id: input }, select: { id: true, name: true, image: true } }); }) }); export type AppRouter = typeof appRouter;
前端React调用代码
import { useQuery } from '@tanstack/react-query'; import { api } from '../utils/trpc'; export default function ProductCard({ productId }: { productId: number }) { const { data: product, error, isLoading } = api.getProductById.useQuery(productId); if (isLoading) return <div>加载中...</div>; if (error) return <div>错误:{error.message}</div>; return ( <div className="product-card"> <h3>{product?.name}</h3> {product?.image && <img src={product.image} alt={product.name} />} </div> ); }
核心问题及解决方法
1. 二进制数据序列化失败(最常见原因)
如果Prisma的image字段是Bytes类型,TRPC默认的JSON序列化无法处理Buffer对象,导致转换失败。
解决步骤:
- 后端将Buffer转为Base64字符串:
// 修改TRPC query方法 .query(async ({ input }) => { const product = await prisma.product.findUnique({ where: { id: input }, select: { id: true, name: true, image: true } }); // 把二进制Buffer转成Base64 if (product?.image) { product.image = product.image.toString('base64'); } return product; }) - 前端拼接图片URI渲染:
{product?.image && ( <img src={`data:image/png;base64,${product.image}`} alt={product.name} /> )}
2. 前后端序列化器不匹配
如果返回的数据包含复杂类型(如Date、Buffer),默认序列化器无法处理,需要使用superjson统一序列化逻辑。
解决步骤:
- 安装依赖:
npm install superjson - 后端配置transformer:
import { initTRPC } from '@trpc/server'; import superjson from 'superjson'; const t = initTRPC.create({ transformer: superjson, }); - 前端客户端同步配置:
// 前端trpc客户端初始化文件 import { createTRPCReact } from '@trpc/react-query'; import superjson from 'superjson'; import type { AppRouter } from '../server/router'; export const api = createTRPCReact<AppRouter>(); export const trpcClient = api.createClient({ url: '/api/trpc', transformer: superjson, });
3. 图片路径访问问题
如果数据库存储的是图片文件的相对路径,直接返回会导致前端无法正确加载。
解决方法:
后端返回时拼接完整的访问URL:
.query(async ({ input }) => { const product = await prisma.product.findUnique({ where: { id: input }, select: { id: true, name: true, image: true } }); if (product?.image) { // 假设图片存储在public/images目录下,拼接绝对路径 product.image = `${process.env.NEXT_PUBLIC_APP_URL}/images/${product.image}`; } return product; })
快速排查技巧
- 直接在后端打印Prisma查询结果,确认
image字段的类型和内容。 - 开启TRPC调试模式,查看服务器返回的原始响应:
// 后端添加日志 import { loggerLink } from '@trpc/server/adapters/standalone'; const t = initTRPC.create({ links: [loggerLink()], }); - 检查前端Network面板,查看TRPC接口的响应内容是否符合预期。
内容的提问来源于stack exchange,提问作者Mackyui
相关产品推荐
相关产品推荐

