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

如何使用React.js将文件与JSON数据固定到Pinata平台

React客户端实现Pinata文件与JSON数据固定方案

问题背景

已掌握服务端固定文件到Pinata的实现方式,现需在React客户端完成文件及JSON数据的Pinata固定操作,服务端参考代码如下:

async function storeImages(imagesFilePath) {
  const fullImagesPath = path.resolve(imagesFilePath);
  const files = fs.readdirSync(fullImagesPath);
  let responses = [];
  console.log("Uploading to Pinata !!!");
  console.log("paths ", fs.createReadStream(fullImagesPath + "/" + files[0]));
  for (fileIndex in files) {
    const readableStreamForFile = fs.createReadStream(
      `${fullImagesPath}/${files[fileIndex]}`
    );
    try {
      const response = await pinata.pinFileToIPFS(readableStreamForFile);
      responses.push(response);
    } catch (error) {
      console.log(error);
    }
  }
  return { responses, files };
}
async function storeTokeUriMetadata(metadata) {
  try {
    const response = await pinata.pinJSONToIPFS(metadata);
    return response;
  } catch (error) {
    console.log(error);
  }
  return null;
}

客户端实现方案

准备工作

  • 安装请求库:npm install axios(或使用原生fetch)
  • 从Pinata控制台获取API Key和API Secret,注意:生产环境禁止在客户端硬编码密钥,建议通过后端代理转发请求,以下示例仅作演示用途

1. 文件上传(固定到IPFS)

创建React组件实现文件选择与上传逻辑:

import axios from 'axios';
import { useState } from 'react';

const PinataFileUpload = () => {
  const [selectedFile, setSelectedFile] = useState(null);
  const [uploadResult, setUploadResult] = useState(null);

  const PINATA_API_KEY = '你的API_KEY';
  const PINATA_API_SECRET = '你的API_SECRET';
  const PINATA_PIN_FILE_URL = 'https://api.pinata.cloud/pinning/pinFileToIPFS';

  const handleFileChange = (e) => {
    setSelectedFile(e.target.files[0]);
  };

  const handleUpload = async () => {
    if (!selectedFile) return;

    const formData = new FormData();
    formData.append('file', selectedFile);

    // 可选:添加自定义元数据
    const metadata = JSON.stringify({
      name: selectedFile.name,
      keyvalues: {
        category: 'react-upload'
      }
    });
    formData.append('pinataMetadata', metadata);

    // 可选:配置IPFS选项
    const pinataOptions = JSON.stringify({
      cidVersion: 0
    });
    formData.append('pinataOptions', pinataOptions);

    try {
      const response = await axios.post(PINATA_PIN_FILE_URL, formData, {
        headers: {
          'Content-Type': `multipart/form-data; boundary=${formData._boundary}`,
          'pinata_api_key': PINATA_API_KEY,
          'pinata_secret_api_key': PINATA_API_SECRET
        }
      });
      setUploadResult(response.data);
      console.log('文件上传成功:', response.data);
    } catch (error) {
      console.error('文件上传失败:', error.response?.data || error.message);
    }
  };

  return (
    <div>
      <input type="file" onChange={handleFileChange} />
      <button onClick={handleUpload} disabled={!selectedFile}>上传到Pinata</button>
      {uploadResult && (
        <div>
          <h3>上传结果</h3>
          <p>IPFS CID: {uploadResult.IpfsHash}</p>
          <p>文件大小: {uploadResult.PinSize} bytes</p>
        </div>
      )}
    </div>
  );
};

export default PinataFileUpload;

2. JSON数据上传(固定到IPFS)

实现JSON元数据的上传逻辑:

import axios from 'axios';
import { useState } from 'react';

const PinataJsonUpload = () => {
  const [metadata, setMetadata] = useState({
    name: '测试NFT元数据',
    description: 'React客户端上传的NFT元数据示例',
    image: 'ipfs://QmXXXXXXXXXXXXXXXXXXXXXX' // 替换为已上传图片的CID
  });
  const [uploadResult, setUploadResult] = useState(null);

  const PINATA_API_KEY = '你的API_KEY';
  const PINATA_API_SECRET = '你的API_SECRET';
  const PINATA_PIN_JSON_URL = 'https://api.pinata.cloud/pinning/pinJSONToIPFS';

  const handleUploadJson = async () => {
    try {
      const response = await axios.post(PINATA_PIN_JSON_URL, metadata, {
        headers: {
          'Content-Type': 'application/json',
          'pinata_api_key': PINATA_API_KEY,
          'pinata_secret_api_key': PINATA_API_SECRET
        }
      });
      setUploadResult(response.data);
      console.log('JSON上传成功:', response.data);
    } catch (error) {
      console.error('JSON上传失败:', error.response?.data || error.message);
    }
  };

  return (
    <div>
      <textarea
        value={JSON.stringify(metadata, null, 2)}
        onChange={(e) => setMetadata(JSON.parse(e.target.value))}
        rows="8"
        cols="50"
      />
      <button onClick={handleUploadJson}>上传JSON到Pinata</button>
      {uploadResult && (
        <div>
          <h3>JSON上传结果</h3>
          <p>IPFS CID: {uploadResult.IpfsHash}</p>
        </div>
      )}
    </div>
  );
};

export default PinataJsonUpload;

核心注意事项

  • 密钥安全:客户端硬编码API密钥存在被盗用风险,生产环境必须通过后端接口转发Pinata请求,避免密钥暴露。
  • 文件限制:Pinata免费用户有文件大小上限,大文件上传前需确认平台规则。
  • 错误处理:示例仅做基础错误捕获,实际项目可根据Pinata返回的错误码添加用户友好提示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.21 07:48:43