· Nacho Coll · Guides · 9 min čtení
Ukládání metadat NFT: Kompletní průvodce IPFS pro tvůrce NFT
Návod krok za krokem k ukládání metadat NFT na IPFS. Obsahuje vzory ERC-721 tokenURI, příklady v Pythonu a JavaScriptu.

Vytváření NFT vyžaduje více než jen nasazení smart contractu — potřebujete spolehlivé, decentralizované úložiště pro vaše metadata a aktiva. Tento komplexní průvodce vás krok za krokem provede ukládáním metadat NFT na IPFS pomocí osvědčených postupů v oboru, s kompletními příklady kódu pro vývojáře v Pythonu a JavaScriptu.

Proč IPFS pro ukládání metadat NFT?
Tradiční webhosting vytváří rizika centralizace pro NFT projekty. Když metadata sídlí na konvenčních serverech, NFT se mohou “rozbít”, pokud hostingová služba spadne nebo změní URL adresy. IPFS (InterPlanetary File System) to řeší poskytováním:
- Neměnné adresování obsahu: Každý soubor obdrží jedinečný Content Identifier (CID), který se nikdy nezmění
- Decentralizované úložiště: Obsah existuje na více uzlech po celém světě
- Kryptografické ověření: Integrita souboru je zaručena hashováním obsahu
- URL odolné vůči budoucnosti: IPFS odkazy fungují neomezeně dlouho a chrání dlouhodobou hodnotu
Pro hlubší pochopení základů IPFS si přečtěte našeho průvodce o tom, co je IPFS pinning.
Pochopení struktury metadat ERC-721
Standard ERC-721 definuje, jak by měla být strukturována metadata NFT. Funkce tokenURI vašeho smart contractu vrací URL ukazující na JSON metadata podle tohoto vzoru:
{
"name": "My Amazing NFT #1",
"description": "A unique digital artwork showcasing...",
"image": "ipfs://QmYourImageCIDHere",
"attributes": [
{
"trait_type": "Background",
"value": "Blue"
},
{
"trait_type": "Rarity",
"value": "Common"
}
],
"external_url": "https://yourproject.com/token/1"
}Klíčová pole metadat
- name: Název NFT zobrazený v peněženkách a tržištích
- description: Podrobné informace o NFT
- image: IPFS URL k hlavnímu vizuálnímu aktivu
- attributes: Vlastnosti založené na rysech pro filtrování a výpočty vzácnosti
- external_url: Volitelný odkaz na další obsah nebo webovou stránku vašeho projektu
Proces ukládání NFT na IPFS krok za krokem
Krok 1: Připravte svá aktiva a metadata
Před nahráním čehokoli si zorganizujte soubory:
- Hlavní aktiva: Obrázky, videa nebo jiný primární obsah
- Soubory metadat: JSON soubory popisující každé NFT
- Metadata kolekce: Volitelné informace na úrovni kolekce
Krok 2: Nahrajte aktiva na IPFS
Začněte nahráváním vašich hlavních NFT aktiv (obrázků, videí atd.), abyste získali jejich IPFS CID. Na tyto CID budete odkazovat ve svých JSON souborech s metadaty.
Zde je návod, jak nahrát obrázek pomocí Pythonu:
import requests
import base64
import json
def upload_image_to_ipfs(image_path, api_key):
"""Upload an image file to IPFS and return its CID"""
# Read and encode image
with open(image_path, 'rb') as f:
image_data = base64.b64encode(f.read()).decode('utf-8')
# Prepare upload payload
payload = {
"content": image_data,
"description": f"NFT Asset: {image_path}"
}
headers = {
"Content-Type": "application/json",
"X-Api-Key": api_key
}
# Upload to IPFS.NINJA
response = requests.post(
"https://api.ipfs.ninja/upload/new",
headers=headers,
json=payload
)
if response.status_code == 200:
result = response.json()
print(f"✅ Image uploaded successfully!")
print(f"CID: {result['cid']}")
print(f"IPFS URL: {result['uris']['ipfs']}")
print(f"Gateway URL: {result['uris']['url']}")
return result['cid']
else:
print(f"❌ Upload failed: {response.text}")
return None
# Example usage
API_KEY = "bws_1234567890abcdef1234567890abcdef" # Replace with your actual key
image_cid = upload_image_to_ipfs("my-nft-artwork.png", API_KEY)Krok 3: Vytvořte a nahrajte JSON metadat
Jakmile máte CID aktiv, vytvořte JSON soubory metadat a nahrajte je:
def create_and_upload_metadata(name, description, image_cid, attributes, api_key):
"""Create NFT metadata JSON and upload to IPFS"""
# Create metadata object
metadata = {
"name": name,
"description": description,
"image": f"ipfs://{image_cid}",
"attributes": attributes
}
# Convert to JSON string and encode
metadata_json = json.dumps(metadata, indent=2)
metadata_b64 = base64.b64encode(metadata_json.encode('utf-8')).decode('utf-8')
# Upload metadata
payload = {
"content": metadata_b64,
"description": f"NFT Metadata: {name}",
"metadata": {
"contentType": "application/json",
"nftTokenId": name.split('#')[1] if '#' in name else "1"
}
}
headers = {
"Content-Type": "application/json",
"X-Api-Key": api_key
}
response = requests.post(
"https://api.ipfs.ninja/upload/new",
headers=headers,
json=payload
)
if response.status_code == 200:
result = response.json()
print(f"✅ Metadata uploaded successfully!")
print(f"Metadata CID: {result['cid']}")
return result['cid']
else:
print(f"❌ Metadata upload failed: {response.text}")
return None
# Example usage
attributes = [
{"trait_type": "Background", "value": "Cosmic Blue"},
{"trait_type": "Eyes", "value": "Laser"},
{"trait_type": "Rarity", "value": "Epic"}
]
metadata_cid = create_and_upload_metadata(
name="Cosmic Warrior #001",
description="A fierce warrior from the distant galaxies, wielding the power of stars.",
image_cid=image_cid,
attributes=attributes,
api_key=API_KEY
)Krok 4: Implementace v JavaScriptu
Pro webové aplikace nebo projekty Node.js zde je JavaScriptový ekvivalent:
class NFTStorage {
constructor(apiKey) {
this.apiKey = apiKey;
this.baseUrl = 'https://api.ipfs.ninja';
}
async uploadFile(fileContent, description) {
const payload = {
content: fileContent, // base64 encoded
description: description
};
const response = await fetch(`${this.baseUrl}/upload/new`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'X-Api-Key': this.apiKey
},
body: JSON.stringify(payload)
});
if (!response.ok) {
throw new Error(`Upload failed: ${response.statusText}`);
}
return await response.json();
}
async uploadImageFromFile(file) {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onload = async (e) => {
try {
const base64Content = e.target.result.split(',')[1]; // Remove data:image/...;base64, prefix
const result = await this.uploadFile(base64Content, `NFT Image: ${file.name}`);
resolve(result.cid);
} catch (error) {
reject(error);
}
};
reader.readAsDataURL(file);
});
}
async uploadMetadata(name, description, imageCid, attributes = []) {
const metadata = {
name,
description,
image: `ipfs://${imageCid}`,
attributes
};
const metadataJson = JSON.stringify(metadata, null, 2);
const base64Metadata = btoa(metadataJson);
const result = await this.uploadFile(base64Metadata, `NFT Metadata: ${name}`);
return result.cid;
}
}
// Usage example
const storage = new NFTStorage('bws_1234567890abcdef1234567890abcdef'); // Replace with your key
// Upload process
async function createNFT() {
try {
// Assuming you have a file input element
const fileInput = document.getElementById('nft-image');
const imageFile = fileInput.files[0];
console.log('Uploading image...');
const imageCid = await storage.uploadImageFromFile(imageFile);
console.log(`Image uploaded: ${imageCid}`);
console.log('Uploading metadata...');
const metadataCid = await storage.uploadMetadata(
'Galaxy Explorer #042',
'A mysterious explorer traversing the cosmic void.',
imageCid,
[
{ trait_type: 'Class', value: 'Explorer' },
{ trait_type: 'Galaxy', value: 'Andromeda' },
{ trait_type: 'Rarity', value: 'Legendary' }
]
);
console.log(`Metadata uploaded: ${metadataCid}`);
console.log(`Token URI: ipfs://${metadataCid}`);
} catch (error) {
console.error('Upload failed:', error);
}
}Implementace tokenURI ve vašem Smart Contractu
Jakmile jsou vaše metadata nahrána na IPFS, implementujte funkci tokenURI ve vašem ERC-721 kontraktu:
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
contract MyNFTCollection is ERC721, Ownable {
mapping(uint256 => string) private _tokenURIs;
string private _baseTokenURI;
constructor(string memory name, string memory symbol) ERC721(name, symbol) {}
function setTokenURI(uint256 tokenId, string memory uri) external onlyOwner {
require(_exists(tokenId), "Token does not exist");
_tokenURIs[tokenId] = uri;
}
function setBaseURI(string memory baseURI) external onlyOwner {
_baseTokenURI = baseURI;
}
function tokenURI(uint256 tokenId) public view virtual override returns (string) {
require(_exists(tokenId), "Token does not exist");
string memory _tokenURI = _tokenURIs[tokenId];
// Return specific token URI if set
if (bytes(_tokenURI).length > 0) {
return _tokenURI;
}
// Fall back to base URI + token ID pattern
if (bytes(_baseTokenURI).length > 0) {
return string(abi.encodePacked(_baseTokenURI, tokenId.toString()));
}
return "";
}
function mintWithURI(address to, uint256 tokenId, string memory uri) external onlyOwner {
_mint(to, tokenId);
_tokenURIs[tokenId] = uri;
}
}Dávkové operace pro velké kolekce
Pro velké NFT kolekce dávkové operace šetří čas a náklady na gas:
def batch_upload_collection(collection_data, api_key):
"""Upload an entire NFT collection in batches"""
print(f"Starting batch upload of {len(collection_data)} NFTs...")
results = []
for i, nft_data in enumerate(collection_data):
print(f"Processing NFT {i+1}/{len(collection_data)}: {nft_data['name']}")
try:
# Upload image
image_cid = upload_image_to_ipfs(nft_data['image_path'], api_key)
if image_cid:
# Upload metadata
metadata_cid = create_and_upload_metadata(
name=nft_data['name'],
description=nft_data['description'],
image_cid=image_cid,
attributes=nft_data['attributes'],
api_key=api_key
)
if metadata_cid:
results.append({
'token_id': i + 1,
'name': nft_data['name'],
'image_cid': image_cid,
'metadata_cid': metadata_cid,
'token_uri': f"ipfs://{metadata_cid}"
})
except Exception as e:
print(f"❌ Error processing {nft_data['name']}: {e}")
print(f"✅ Batch upload complete! {len(results)} NFTs processed successfully.")
return results
# Example collection data
collection_data = [
{
'name': 'Cosmic Warrior #001',
'description': 'A fierce warrior from distant galaxies.',
'image_path': 'images/warrior_001.png',
'attributes': [
{'trait_type': 'Class', 'value': 'Warrior'},
{'trait_type': 'Rarity', 'value': 'Epic'}
]
},
# Add more NFTs...
]
results = batch_upload_collection(collection_data, API_KEY)Osvědčené postupy pro ukládání metadat NFT
1. Používejte popisné názvy souborů
Při nahrávání na IPFS používejte smysluplné popisy, které pomohou s organizací:
payload = {
"content": base64_content,
"description": f"Collection: {collection_name} | Token: {token_id} | Type: {file_type}"
}2. Implementujte správné zpracování chyb
Vždy zpracujte selhání nahrávání elegantně:
import time
def upload_with_retry(upload_function, max_retries=3, delay=2):
"""Upload with exponential backoff retry logic"""
for attempt in range(max_retries):
try:
return upload_function()
except Exception as e:
if attempt == max_retries - 1:
raise e
print(f"Attempt {attempt + 1} failed: {e}. Retrying in {delay} seconds...")
time.sleep(delay)
delay *= 2 # Exponential backoff3. Validujte strukturu metadat
Ujistěte se, že vaše metadata splňují standardy:
def validate_metadata(metadata):
"""Validate NFT metadata structure"""
required_fields = ['name', 'description', 'image']
for field in required_fields:
if field not in metadata:
raise ValueError(f"Missing required field: {field}")
if not metadata['image'].startswith('ipfs://'):
raise ValueError("Image must be an IPFS URL")
if 'attributes' in metadata:
for attr in metadata['attributes']:
if 'trait_type' not in attr or 'value' not in attr:
raise ValueError("Invalid attribute structure")
return TrueVýběr správné IPFS Pinning služby
Při výběru IPFS pinning služby pro váš NFT projekt zvažte:
- Spolehlivost: Garantovaná doba provozu pro dlouhodobé úložiště
- Výkon: Rychlé rychlosti načítání po celém světě
- Cena: Cenově efektivní pro velikost vaší kolekce
- Funkce: Schopnosti API, analytika a vývojářské nástroje
Pro podrobné srovnání pinning služeb si přečtěte naše srovnání IPFS Ninja vs Pinata a našeho průvodce nejlepšími IPFS pinning službami.
Pokročilé funkce: Vlastní brány a analytika
IPFS Ninja nabízí další funkce pro profesionální NFT projekty:
Konfigurace vlastní brány
Vytvořte značkové IPFS brány pro vaši kolekci:
// Access your NFT through a custom gateway
const customGateway = 'https://my-collection.gw.ipfs.ninja';
const nftUrl = `${customGateway}/ipfs/${metadataCid}`;Analytika nahrávání
Sledujte využití úložiště NFT a vzory přístupu prostřednictvím analytiky dashboardu, což vám pomůže pochopit výkon kolekce a optimalizovat náklady na úložiště.
Řešení běžných problémů
Metadata se nenačítají
- Ověřte, že IPFS URL používají protokol
ipfs:// - Zkontrolujte, zda je JSON metadat platný
- Ujistěte se, že pinning služba udržuje obsah
Obrázky se nezobrazují
- Potvrďte, že CID obrázků jsou v metadatech správné
- Otestujte URL obrázků v IPFS bránách
- Ověřte, že formáty obrázkových souborů jsou kompatibilní s webem
Chyby odhadu gas
- Ujistěte se, že funkce
tokenURIvrací platné řetězce - Zkontrolujte cyklické odkazy v metadatech
- Validujte všechna IPFS CID před mintingem
Monitorování a údržba vašeho NFT úložiště
Po nasazení vaší kolekce:
- Pravidelné kontroly stavu: Ověřte, že metadata a obrázky zůstávají přístupné
- Zálohujte důležitá CID: Veďte záznamy o všech nahraných identifikátorech obsahu
- Sledujte analytiku: Sledujte vzory přístupu a využití úložiště
- Plánujte škálování: Zvažte upgradování své pinning služby, jak vaše kolekce roste
Pro více podrobností o programovém správě nahrávání si přečtěte našeho IPFS upload API tutoriál.
Závěr
Ukládání metadat NFT na IPFS zajišťuje, že vaše digitální aktiva zůstanou dlouhodobě přístupná a hodnotná. Sledováním tohoto průvodce jste se naučili:
- Strukturovat metadata kompatibilní s ERC-721
- Nahrávat aktiva a metadata pomocí Pythonu a JavaScriptu
- Implementovat vhodné funkce
tokenURI - Zvládat dávkové operace pro velké kolekce
- Aplikovat osvědčené postupy pro produkční nasazení
Kombinace decentralizované architektury IPFS a spolehlivých pinning služeb vytváří základ pro úspěšné NFT projekty, které obstojí ve zkoušce času.
Připraveni začít s pinningem? Vytvořte si bezplatný účet — 50 souborů, 1 GB úložiště, 2 GB šířky pásma/měsíc. Není potřeba kreditní karta.
