如何使用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
相关产品推荐
相关产品推荐

