Next.js 14路由处理器返回Blob时res.blob()停滞问题排查
问题排查与解决方案
核心问题分析
你的代码里await res.blob()永久停滞,大概率是路由处理器返回的Response缺少必要的响应头信息,导致客户端无法正确识别Blob的边界,一直等待数据传输完成。
当你从https://picsum.photos/200/300获取响应后,转成Blob再包装成新Response返回时,丢失了原响应的Content-Type、Content-Length等关键头部,客户端fetch无法判断Blob是否接收完毕,从而卡住。
修复方案
方案1:直接转发外部响应(推荐)
不需要将外部响应转成Blob,直接返回原Response,这样会自动保留所有必要的头部信息:
// /test/api/route.ts export async function GET(request: Request) { const res = await fetch("https://picsum.photos/200/300"); // 直接返回外部响应,保留所有头部和流数据 return res; }
方案2:手动添加响应头后返回Blob
如果必须转成Blob再返回,需要从原响应中提取并设置正确的Content-Type:
// /test/api/route.ts export async function GET(request: Request) { const res = await fetch("https://picsum.photos/200/300"); const blob = await res.blob(); // 从原响应获取Content-Type,设置到新Response中 return new Response(blob, { headers: { "Content-Type": res.headers.get("Content-Type") || "image/jpeg", "Content-Length": blob.size.toString(), }, }); }
客户端代码优化(可选但重要)
你的useEffect没有设置依赖数组,会导致组件每次渲染都重复调用getData,添加空依赖数组避免不必要的重复请求:
"use client"; import React, { useEffect } from "react"; const page = () => { useEffect(() => { const getData = async () => { const res = await fetch("/test/api"); console.log(res); const blob = await res.blob(); console.log("blob"); }; getData(); }, []); // 添加空依赖数组 return <div>page</div>; }; export default page;
验证方法
修改路由处理器后,重新启动Next.js服务,客户端组件加载后,await res.blob()会正常执行,控制台会打印"blob"。
内容的提问来源于stack exchange,提问作者Andrew Chen
相关产品推荐
相关产品推荐

