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

请求IPFS数据触发FetchError,Express应用崩溃求助

IPFS请求返回非JSON导致Express崩溃的解决方法

错误日志

FetchError: invalid json response body at https://gateway.pinata.cloud/ipfs/Qmc79GYqhAvU1qpDCJ4Ji37fWt2EoerqqxHb7e7bxakkFX reason: Unexpected token < in JSON at position 0
at E:\MEDIBLOCK\backend\node_modules\node-fetch\lib\index.js:273:32
at processTicksAndRejections (node:internal/process/task_queues:96:5)
at async Object.getDataFromIPFS (file:///E:/MEDIBLOCK/backend/controller/auth/ipfsServices.js:57:20)
at async getAllDoctors (file:///E:/MEDIBLOCK/backend/controller/auth/doctorController.js:147:24) {
type: 'invalid-json'
}

错误原因

这个错误核心是:请求的IPFS网关返回的不是JSON数据,而是HTML(开头的<是HTML标签起始符号),大概率是以下情况:

  • IPFS哈希无效或对应文件未上传成功
  • Pinata网关返回了错误页面(如404、限流提示)
  • 合约中存储的IPFS哈希存在拼写/格式错误

解决步骤

1. 验证IPFS哈希有效性

直接在浏览器打开报错的IPFS链接https://gateway.pinata.cloud/ipfs/Qmc79GYqhAvU1qpDCJ4Ji37fWt2EoerqqxHb7e7bxakkFX:

  • 如果返回HTML错误页(比如404),说明哈希无效,需确认合约中存储的哈希是否正确,以及IPFS文件是否上传成功
  • 如果返回正常JSON,再排查代码请求逻辑

2. 强化IPFS请求的错误处理

当前getDataFromIPFS的错误处理不完整:仅捕获请求异常,但如果返回200状态码但内容不是JSON,response.json()会抛错,且当前catch仅打印日志,返回undefined会导致后续result.phoneNo赋值崩溃。

修改后的getDataFromIPFS代码:

async getDataFromIPFS(hash) {
  try {
    const response = await fetch(`https://gateway.pinata.cloud/ipfs/${hash}`, { mode: "cors" });
    // 先检查响应状态是否正常
    if (!response.ok) {
      throw new Error(`IPFS请求失败,状态码:${response.status}`);
    }
    // 单独捕获JSON解析错误
    try {
      const data = await response.json();
      return data;
    } catch (parseError) {
      console.error(`解析IPFS数据失败,哈希:${hash}`, parseError);
      // 返回标记无效的数据,避免后续崩溃
      return { invalid: true, hash };
    }
  } catch (error) {
    console.error(`请求IPFS失败,哈希:${hash}`, error);
    return { failed: true, hash };
  }
},

3. 在医生数据获取逻辑中过滤无效数据

修改getAllDoctors,跳过无效的IPFS返回结果,避免因undefined或错误对象导致崩溃:

async getAllDoctors(req, res, next) { 
  try {
    const contract = new web3.eth.Contract(hospitABI, contarct_address);
    const allAddress = await contract.methods.getDoctorAddresses().call();
    let allInfo = [];
    for (let i = 0; i < allAddress.length; i++) {
      const doctor = await contract.methods
       .GetDoctorByAddress(allAddress[i])
        .call();
      allInfo = allInfo.concat(doctor);
    }

    const info = [];
    for (let i = 1; i < allInfo.length; i++) {
      const hash = allInfo[i]["0"];
      const result = await ipfsServiceController.getDataFromIPFS(hash);
      // 仅处理有效数据
      if (result && !result.invalid && !result.failed) {
        result.phoneNo = allInfo[i]["1"]; 
        info.push(result);
      } else {
        console.warn(`跳过无效医生数据,哈希:${hash}`);
      }
    }
    res.send(info);
  } catch (error) {
    console.log("main -> " + error);
    // 给前端返回错误响应,避免请求挂起
    res.status(500).send({ error: "获取医生列表失败" });
  }
}

4. 尝试更换IPFS网关

Pinata网关可能存在访问限制,可替换为其他公共网关测试,比如:

  • https://ipfs.io/ipfs/${hash}
  • https://cloudflare-ipfs.com/ipfs/${hash}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 01:58:26