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

基于React/Express/Node.js的NFT铸造项目:Pinata IPFS pinFileToIPFS方法无法接收用户上传文件求助

问题分析与解决方案

兄弟,我一眼就发现你代码里的核心问题了——你调用了错误的Pinata API端点!你现在用的是pinJSONToIPFS,这个接口是专门用来上传JSON元数据的,而你要上传图片文件,应该用pinFileToIPFS的端点。这就是为什么你会收到requires valid JSON的错误提示。

除此之外,你的Base64处理也可能存在小问题,我帮你一步步修正:

1. 替换正确的API端点

把const url = "https://api.pinata.cloud/pinning/pinJSONToIPFS";改成:

const url = "https://api.pinata.cloud/pinning/pinFileToIPFS";

2. 处理Base64字符串的前缀

用户上传的Base64字符串通常会带有前缀(比如data:image/png;base64,),这个前缀会导致Buffer转换出错,所以要先移除它:

// 移除Base64前缀(如果存在)
const base64WithoutPrefix = image.startsWith('data:') ? image.split(',')[1] : image;
const buffer = Buffer.from(base64WithoutPrefix, 'base64');

3. 优化请求头设置

Axios会自动处理multipart/form-data的boundary,不需要手动设置,手动设置反而可能导致格式错误,所以可以去掉这个头,改用formData.getHeaders()自动生成正确的请求头。

4. 完善路由响应

你的当前路由没有给客户端返回任何结果,应该把Pinata的响应或错误返回给前端,方便调试。

修正后的完整代码

const axios = require('axios');
const FormData = require('form-data');
const router = require('express').Router();
const { Readable } = require('stream');

const pinFileToIPFS = async (image) => {
  try {
    // 替换为正确的文件上传端点
    const url = `https://api.pinata.cloud/pinning/pinFileToIPFS`;
    // 移除Base64前缀(如果存在)
    const base64WithoutPrefix = image.startsWith('data:') ? image.split(',')[1] : image;
    const buffer = Buffer.from(base64WithoutPrefix, 'base64');
    const stream = Readable.from(buffer);
    const filename = `an-awesome-nft_${Date.now()}.png`;
    stream.path = filename;
    
    const formData = new FormData();
    formData.append("file", stream);
    
    // 可选:添加自定义元数据(方便后续管理IPFS文件)
    formData.append("pinataMetadata", JSON.stringify({
      name: filename,
      keyvalues: {
        nft: "true"
      }
    }));

    const response = await axios.post(url, formData, {
      headers: {
        ...formData.getHeaders(), // 让FormData自动生成正确的请求头
        'pinata_api_key': "*******************",
        'pinata_secret_api_key': "**********************************",
      }
    });
    console.log("Success: ", response.data);
    return response.data;
  } catch (error) {
    console.log("Fail! ", error.response?.data || error.message);
    throw error;
  }
};

router.route('/').post(async (req, res) => {
  try {
    const image = req.body.image;
    const pinataResult = await pinFileToIPFS(image);
    res.status(200).json(pinataResult);
  } catch (error) {
    res.status(500).json({ error: error.response?.data || error.message });
  }
});

module.exports = router;

额外建议

  • 不要硬编码API密钥:把你的Pinata密钥放在环境变量里(比如用dotenv包),避免代码泄露导致密钥被盗用。
  • 客户端优化:客户端可以直接上传文件二进制数据(用FormData),而不是转成Base64,这样能减少数据传输量,提升上传效率。
  • 调试技巧:可以先用Postman测试Pinata的pinFileToIPFS接口,确保API调用正常后再集成到代码里,这样更容易定位问题。

你的整体实现思路是完全没问题的:上传图片到IPFS → 生成包含IPFS URI的元数据 → 铸造NFT,这是NFT铸造的标准流程,作为Web3新手能想到这个流程已经很棒了,继续加油!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.28 10:12:40