You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

升级NextJS 13后使用createObjectURL无法创建图片文件

问题分析与解决方案

核心问题

你遇到的问题根源在于二进制数据通过JSON传输时被损坏:

  • 服务器端用res.json()返回arrayBuffer时,Node会把二进制数据转换成普通JavaScript数组(每个字节对应数组元素),丢失了原始二进制的结构。
  • 客户端用res.json()接收后得到的是这个数组,而非原始ArrayBuffer,转成Blob后数据已损坏,导致URL.createObjectURL生成的URL无法正确解析图片。

旧版本环境能工作是巧合(比如隐式的转换兼容),但这种传输方式本身不符合规范,升级后NextJS/Node的处理逻辑严格化,问题就暴露了。

修复代码

1. 修改API路由(pages/api/getImageData.js)

直接返回二进制数据流,避免JSON转换:

import axios from "axios";
export default async (req, res) => {
  // 改为JSON格式传参,避免body解析问题
  const { url: imageUrlStr } = req.body;
  const imageUrl = new URL(imageUrlStr);
  
  const imageData = await axios.get(imageUrl.toString(), {
    responseType: 'arraybuffer',
  });
  
  // 从响应头获取真实图片类型,替代模糊的image/*
  const contentType = imageData.headers['content-type'] || 'image/jpeg';
  res.setHeader('Content-Type', contentType);
  
  // 直接发送二进制数据,不转JSON
  res.status(200).send(imageData.data);
}

2. 修改客户端代码(pages/index.js)

直接获取原始ArrayBuffer,再生成Blob:

await fetch("/api/getImageData", {
  method: "POST",
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({ url: fileSrc }) // 改为JSON格式传参
})
.then(res => {
  // 获取响应头里的图片类型
  const contentType = res.headers.get('content-type') || 'image/jpeg';
  return Promise.all([res.arrayBuffer(), contentType]);
})
.then(([bufferData, contentType]) => new Blob([bufferData], { type: contentType }))
.then(blob => {
  console.log(blob)
  try {
    const url = URL.createObjectURL(blob)
    console.log("Image created: " + url)
    // 这里可以用该URL展示图片或保存文件
  } catch(e) {
    console.log(e)
  }
})

额外说明

  • 为什么用res.send()而非res.json():res.send()会直接传输原始二进制数据,不会做JSON序列化,保证数据完整性。
  • 规范传参方式:把图片URL放在JSON对象里传输,避免NextJS 13中API路由对raw body解析的潜在问题。

内容的提问来源于stack exchange,提问作者daviddev95

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 21:08:29