· Nacho Coll · Tutorials  · 9 Min. Lesezeit

Python IPFS Upload: Vollständiger Leitfaden mit Code-Beispielen

Lade Dateien von Python zu IPFS hoch mit der IPFS.NINJA REST API. Vollständiger Leitfaden mit Beispielen der requests-Bibliothek.

Lade Dateien von Python zu IPFS hoch mit der IPFS.NINJA REST API. Vollständiger Leitfaden mit Beispielen der requests-Bibliothek.

Python-Entwickler, die Dateien zu IPFS hochladen möchten, müssen keinen lokalen IPFS-Knoten betreiben oder mit komplexen Bibliotheksabhängigkeiten umgehen. Während IPFS.NINJA kein dediziertes Python SDK bereitstellt, ist seine REST-API perfekt für Python-Anwendungen geeignet, die die eingebaute requests-Bibliothek verwenden.

Dieser Leitfaden zeigt Ihnen, wie Sie Dateien, Bilder und JSON-Daten von Python zu IPFS hochladen, Ihre gepinnten Dateien verwalten und erweiterte Funktionen wie signierte Upload-Token für sichere clientseitige Uploads nutzen können.

IPFS Ninja

Warum IPFS.NINJA für die Python-Entwicklung wählen?

Bevor wir in die Code-Beispiele eintauchen, lassen Sie uns verstehen, warum IPFS.NINJA eine ausgezeichnete Wahl für Python-Entwickler ist:

  • Keine SDK-Abhängigkeiten: Verwenden Sie Pythons eingebaute requests-Bibliothek
  • RESTful API: Saubere, vorhersehbare Endpunkte, die HTTP-Standards folgen
  • JSON-nativ: Lade JSON-Daten direkt ohne Dateikonvertierung hoch
  • Mehrere Authentifizierungsmethoden: API-Schlüssel, signierte Token oder JWT
  • Eingebaute Analytics: Verfolge Upload-Performance und Nutzung
  • Benutzerdefinierte Gateways: Branded IPFS-Zugriff für deine Anwendungen

Wenn Sie neu bei IPFS-Pinning-Konzepten sind, lesen Sie unseren umfassenden Leitfaden, was IPFS-Pinning ist und wie man Dateien auf IPFS hochlädt.

Einrichten Ihrer Python-Umgebung

Stellen Sie zunächst sicher, dass Sie Python 3.6+ haben und installieren Sie die erforderlichen Bibliotheken:

pip install requests

Für Bildverarbeitungsbeispiele später in diesem Leitfaden:

pip install Pillow  # Für die Bildverarbeitung

Authentifizierungs-Setup

Alle IPFS.NINJA-API-Aufrufe erfordern Authentifizierung. Die einfachste Methode für Python-Anwendungen ist die Verwendung von API-Schlüsseln mit dem X-Api-Key-Header.

import requests
import json
import base64

# Ihr IPFS.NINJA API-Schlüssel (Format: bws_ + 32 Hex-Zeichen)
API_KEY = "bws_1234567890abcdef1234567890abcdef"
BASE_URL = "https://api.ipfs.ninja"

# Standard-Header für alle Anfragen
headers = {
    "X-Api-Key": API_KEY,
    "Content-Type": "application/json"
}

Erhalten Sie Ihren API-Schlüssel über das IPFS.NINJA-Dashboard, nachdem Sie Ihr Konto erstellt haben.

Hochladen von JSON-Daten zu IPFS

Eine der einzigartigen Funktionen von IPFS.NINJA ist die native JSON-Unterstützung. Sie müssen JSON nicht in Dateien konvertieren — laden Sie Objekte direkt hoch:

def upload_json_to_ipfs(data, description=None, metadata=None):
    """
    JSON-Daten direkt zu IPFS hochladen
    
    Args:
        data (dict): Die hochzuladenden JSON-Daten
        description (str, optional): Beschreibung für die Datei
        metadata (dict, optional): Zusätzliche Metadaten
    
    Returns:
        dict: Antwort mit CID und Zugriffs-URLs
    """
    payload = {
        "content": data,
        "description": description,
        "metadata": metadata
    }
    
    response = requests.post(
        f"{BASE_URL}/upload/new",
        headers=headers,
        json=payload
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f"Upload failed: {response.status_code} - {response.text}")

# Beispiel: Benutzerprofil hochladen
user_profile = {
    "name": "Alice Smith",
    "bio": "Python developer and IPFS enthusiast",
    "website": "https://alice.dev",
    "social": {
        "github": "alicesmith",
        "twitter": "@alice_dev"
    }
}

try:
    result = upload_json_to_ipfs(
        data=user_profile,
        description="User profile for Alice Smith",
        metadata={"type": "profile", "version": "1.0"}
    )
    
    print(f"✅ Upload successful!")
    print(f"CID: {result['cid']}")
    print(f"Size: {result['sizeMB']} MB")
    print(f"IPFS URL: {result['uris']['ipfs']}")
    print(f"Gateway URL: {result['uris']['url']}")
    
except Exception as e:
    print(f"❌ Upload failed: {e}")

Hochladen von Dateien mit Base64-Kodierung

Für Binärdateien wie Bilder, Dokumente oder jeden Dateityp verwenden Sie Base64-Kodierung:

def upload_file_to_ipfs(file_path, description=None, metadata=None):
    """
    Eine Datei mit Base64-Kodierung zu IPFS hochladen
    
    Args:
        file_path (str): Pfad zur hochzuladenden Datei
        description (str, optional): Beschreibung für die Datei
        metadata (dict, optional): Zusätzliche Metadaten
    
    Returns:
        dict: Antwort mit CID und Zugriffs-URLs
    """
    try:
        with open(file_path, "rb") as file:
            file_content = base64.b64encode(file.read()).decode('utf-8')
        
        payload = {
            "content": file_content,
            "description": description or f"File upload: {file_path}",
            "metadata": metadata
        }
        
        response = requests.post(
            f"{BASE_URL}/upload/new",
            headers=headers,
            json=payload
        )
        
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"Upload failed: {response.status_code} - {response.text}")
            
    except FileNotFoundError:
        raise Exception(f"File not found: {file_path}")

# Beispiel: Ein Bild hochladen
try:
    result = upload_file_to_ipfs(
        file_path="./logo.png",
        description="Company logo",
        metadata={
            "type": "image",
            "format": "png",
            "purpose": "branding"
        }
    )
    
    print(f"✅ Image uploaded successfully!")
    print(f"CID: {result['cid']}")
    print(f"View at: {result['uris']['url']}")
    
except Exception as e:
    print(f"❌ Upload failed: {e}")

Batch-Upload-Funktion

Für effizientes Hochladen mehrerer Dateien:

import os
from pathlib import Path

def batch_upload_files(directory_path, file_extensions=None):
    """
    Mehrere Dateien aus einem Verzeichnis hochladen
    
    Args:
        directory_path (str): Verzeichnis mit hochzuladenden Dateien
        file_extensions (list, optional): Nach Dateierweiterungen filtern (z.B., ['.png', '.jpg'])
    
    Returns:
        list: Ergebnisse von jedem Upload
    """
    results = []
    directory = Path(directory_path)
    
    if not directory.exists():
        raise Exception(f"Directory not found: {directory_path}")
    
    # Alle Dateien holen oder nach Erweiterungen filtern
    if file_extensions:
        files = []
        for ext in file_extensions:
            files.extend(directory.glob(f"*{ext}"))
    else:
        files = [f for f in directory.iterdir() if f.is_file()]
    
    print(f"Found {len(files)} files to upload...")
    
    for file_path in files:
        try:
            print(f"Uploading {file_path.name}...")
            
            result = upload_file_to_ipfs(
                file_path=str(file_path),
                description=f"Batch upload: {file_path.name}",
                metadata={
                    "batch_upload": True,
                    "original_name": file_path.name,
                    "file_size": file_path.stat().st_size
                }
            )
            
            results.append({
                "filename": file_path.name,
                "success": True,
                "cid": result['cid'],
                "url": result['uris']['url']
            })
            
        except Exception as e:
            results.append({
                "filename": file_path.name,
                "success": False,
                "error": str(e)
            })
            print(f"Failed to upload {file_path.name}: {e}")
    
    return results

# Beispiel-Verwendung
try:
    results = batch_upload_files("./images", file_extensions=['.png', '.jpg', '.jpeg'])
    
    successful = [r for r in results if r['success']]
    failed = [r for r in results if not r['success']]
    
    print(f"\n✅ Successfully uploaded: {len(successful)} files")
    print(f"❌ Failed uploads: {len(failed)} files")
    
    for result in successful:
        print(f"  - {result['filename']}: {result['url']}")
        
except Exception as e:
    print(f"Batch upload error: {e}")

Verwalten Ihrer gepinnten Dateien

Abrufen und Verwalten Ihrer hochgeladenen Dateien:

def list_pinned_files(limit=50, offset=0):
    """
    Ihre gepinnten Dateien auflisten
    
    Args:
        limit (int): Anzahl der abzurufenden Dateien (max. 100)
        offset (int): Anzahl der zu überspringenden Dateien
    
    Returns:
        dict: Antwort mit Dateiliste und Paginierung
    """
    params = {
        "limit": limit,
        "offset": offset
    }
    
    response = requests.get(
        f"{BASE_URL}/files",
        headers=headers,
        params=params
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f"Failed to list files: {response.status_code} - {response.text}")

def get_file_details(cid):
    """
    Details für eine bestimmte Datei abrufen
    
    Args:
        cid (str): Der Content Identifier der Datei
    
    Returns:
        dict: Dateidetails
    """
    response = requests.get(
        f"{BASE_URL}/files/{cid}",
        headers=headers
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f"Failed to get file details: {response.status_code} - {response.text}")

# Beispiel: Aktuelle Uploads auflisten
try:
    files = list_pinned_files(limit=10)
    
    print(f"Total files: {files.get('total', 0)}")
    print("\nRecent uploads:")
    
    for file_info in files.get('files', []):
        print(f"  - {file_info['cid'][:12]}... | {file_info['sizeMB']} MB | {file_info['description']}")
        
except Exception as e:
    print(f"Failed to list files: {e}")

Vorhandene IPFS-Inhalte pinnen

Pinne Inhalte, die bereits auf IPFS existieren:

def pin_existing_cid(cid, description=None):
    """
    Vorhandene IPFS-Inhalte per CID pinnen
    
    Args:
        cid (str): Der zu pinnende Content Identifier
        description (str, optional): Beschreibung für den gepinnten Inhalt
    
    Returns:
        dict: Antwort mit Pin-Status
    """
    payload = {
        "cid": cid,
        "description": description or f"Pinned existing content: {cid}"
    }
    
    response = requests.post(
        f"{BASE_URL}/pin",
        headers=headers,
        json=payload
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f"Pin failed: {response.status_code} - {response.text}")

# Beispiel: Beliebte NFT-Metadaten pinnen
try:
    result = pin_existing_cid(
        cid="QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG",
        description="Popular NFT metadata backup"
    )
    
    print(f"✅ Successfully pinned existing content!")
    print(f"CID: {result['cid']}")
    
except Exception as e:
    print(f"❌ Pin failed: {e}")

Verwenden von signierten Upload-Token

Für sichere clientseitige Uploads oder temporären Zugriff verwenden Sie signierte Token:

def create_upload_token(expires_in_hours=24, max_uses=None):
    """
    Einen signierten Upload-Token für temporäre Uploads erstellen
    
    Args:
        expires_in_hours (int): Ablaufzeit des Tokens in Stunden
        max_uses (int, optional): Maximale Anzahl von Verwendungen (unbegrenzt wenn None)
    
    Returns:
        dict: Token-Details einschließlich der signierten Token-Zeichenfolge
    """
    from datetime import datetime, timedelta
    
    expiry_time = datetime.utcnow() + timedelta(hours=expires_in_hours)
    
    payload = {
        "expiry": expiry_time.isoformat() + "Z",
        "maxUses": max_uses
    }
    
    response = requests.post(
        f"{BASE_URL}/upload-tokens",
        headers=headers,
        json=payload
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f"Token creation failed: {response.status_code} - {response.text}")

def upload_with_token(data, token, description=None):
    """
    Hochladen mit signiertem Token anstelle eines API-Schlüssels
    
    Args:
        data: Hochzuladender Inhalt (dict für JSON, base64-String für Dateien)
        token (str): Signierter Upload-Token
        description (str, optional): Beschreibung für den Upload
    
    Returns:
        dict: Upload-Antwort
    """
    token_headers = {
        "Authorization": f"Signed {token}",
        "Content-Type": "application/json"
    }
    
    payload = {
        "content": data,
        "description": description
    }
    
    response = requests.post(
        f"{BASE_URL}/upload/new",
        headers=token_headers,
        json=payload
    )
    
    if response.status_code == 200:
        return response.json()
    else:
        raise Exception(f"Token upload failed: {response.status_code} - {response.text}")

# Beispiel: Token für clientseitige Uploads erstellen
try:
    token_info = create_upload_token(expires_in_hours=1, max_uses=10)
    upload_token = token_info['token']
    
    print(f"Created upload token: {upload_token[:20]}...")
    print(f"Expires: {token_info['expiry']}")
    print(f"Max uses: {token_info.get('maxUses', 'unlimited')}")
    
    # Den Token für einen Upload verwenden
    test_data = {"message": "Hello from signed token!"}
    result = upload_with_token(test_data, upload_token, "Token test upload")
    
    print(f"✅ Token upload successful: {result['cid']}")
    
except Exception as e:
    print(f"❌ Token operation failed: {e}")

Vollständiges Beispiel: NFT-Metadaten-Uploader

Hier ist ein praktisches Beispiel, das mehrere Konzepte für die NFT-Metadaten-Verwaltung kombiniert:

class NFTMetadataUploader:
    def __init__(self, api_key):
        self.api_key = api_key
        self.base_url = "https://api.ipfs.ninja"
        self.headers = {
            "X-Api-Key": api_key,
            "Content-Type": "application/json"
        }
    
    def upload_nft_image(self, image_path, name, description=""):
        """NFT-Bild hochladen und IPFS-URL zurückgeben"""
        try:
            with open(image_path, "rb") as file:
                image_content = base64.b64encode(file.read()).decode('utf-8')
            
            payload = {
                "content": image_content,
                "description": f"NFT Image: {name}",
                "metadata": {
                    "type": "nft_image",
                    "name": name,
                    "description": description
                }
            }
            
            response = requests.post(
                f"{self.base_url}/upload/new",
                headers=self.headers,
                json=payload
            )
            
            if response.status_code == 200:
                result = response.json()
                return result['uris']['ipfs']  # IPFS-URI zurückgeben
            else:
                raise Exception(f"Image upload failed: {response.text}")
                
        except Exception as e:
            raise Exception(f"Failed to upload image {image_path}: {e}")
    
    def upload_nft_metadata(self, name, description, image_ipfs_url, attributes=None, external_url=None):
        """Vollständige NFT-Metadaten hochladen"""
        metadata = {
            "name": name,
            "description": description,
            "image": image_ipfs_url,
        }
        
        if attributes:
            metadata["attributes"] = attributes
        if external_url:
            metadata["external_url"] = external_url
        
        payload = {
            "content": metadata,
            "description": f"NFT Metadata: {name}",
            "metadata": {
                "type": "nft_metadata",
                "standard": "ERC-721"
            }
        }
        
        response = requests.post(
            f"{self.base_url}/upload/new",
            headers=self.headers,
            json=payload
        )
        
        if response.status_code == 200:
            return response.json()
        else:
            raise Exception(f"Metadata upload failed: {response.text}")
    
    def create_complete_nft(self, image_path, name, description, attributes=None, external_url=None):
        """Bild und Metadaten für einen vollständigen NFT hochladen"""
        print(f"Creating NFT: {name}")
        
        # Schritt 1: Bild hochladen
        print("  1. Uploading image...")
        image_ipfs_url = self.upload_nft_image(image_path, name, description)
        print(f"     Image IPFS URL: {image_ipfs_url}")
        
        # Schritt 2: Metadaten hochladen
        print("  2. Uploading metadata...")
        metadata_result = self.upload_nft_metadata(
            name=name,
            description=description,
            image_ipfs_url=image_ipfs_url,
            attributes=attributes,
            external_url=external_url
        )
        
        print(f"     Metadata CID: {metadata_result['cid']}")
        print(f"     Metadata URL: {metadata_result['uris']['url']}")
        
        return {
            "image_ipfs": image_ipfs_url,
            "metadata_cid": metadata_result['cid'],
            "metadata_url": metadata_result['uris']['url'],
            "metadata_ipfs": metadata_result['uris']['ipfs']
        }

# Beispiel-Verwendung
if __name__ == "__main__":
    uploader = NFTMetadataUploader("bws_1234567890abcdef1234567890abcdef")
    
    try:
        nft_result = uploader.create_complete_nft(
            image_path="./nft_artwork.png",
            name="Cosmic Cat #001",
            description="A rare cosmic cat exploring the digital universe",
            attributes=[
                {"trait_type": "Background", "value": "Space"},
                {"trait_type": "Species", "value": "Cosmic Cat"},
                {"trait_type": "Rarity", "value": "Legendary"},
                {"trait_type": "Power Level", "value": 95}
            ],
            external_url="https://myproject.com/nft/1"
        )
        
        print("\n🎉 NFT created successfully!")
        print(f"Use this metadata URI in your smart contract: {nft_result['metadata_ipfs']}")
        
    except Exception as e:
        print(f"❌ NFT creation failed: {e}")

Fehlerbehandlung und Best Practices

Implementiere robuste Fehlerbehandlung für Produktionsanwendungen:

import time
from functools import wraps

def retry_on_failure(max_retries=3, delay=1):
    """Decorator zum Wiederholen fehlgeschlagener Uploads"""
    def decorator(func):
        @wraps(func)
        def wrapper(*args, **kwargs):
            for attempt in range(max_retries):
                try:
                    return func(*args, **kwargs)
                except Exception as e:
                    if attempt == max_retries - 1:
                        raise e
                    print(f"Attempt {attempt + 1} failed: {e}")
                    print(f"Retrying in {delay} seconds...")
                    time.sleep(delay)
            return None
        return wrapper
    return decorator

@retry_on_failure(max_retries=3, delay=2)
def robust_upload(file_path, description=None):
    """Hochladen mit automatischem Wiederholungsversuch bei Fehler"""
    return upload_file_to_ipfs(file_path, description)

def validate_api_response(response, operation="operation"):
    """API-Antwort validieren und detaillierte Fehlerinfo bereitstellen"""
    if response.status_code == 200:
        return response.json()
    elif response.status_code == 401:
        raise Exception(f"Authentication failed for {operation}. Check your API key.")
    elif response.status_code == 413:
        raise Exception(f"File too large for {operation}. Check your plan limits.")
    elif response.status_code == 429:
        raise Exception(f"Rate limit exceeded for {operation}. Please wait and retry.")
    else:
        raise Exception(f"{operation} failed: {response.status_code} - {response.text}")

Nächste Schritte

Sie haben jetzt ein komplettes Toolkit zum Hochladen von Dateien zu IPFS von Python aus! Dies deckt ab:

  • JSON- und Datei-Uploads mit der IPFS.NINJA-API
  • Batch-Verarbeitung für mehrere Dateien
  • Dateiverwaltung und Pinnen vorhandener Inhalte
  • Sichere Uploads mit signierten Token
  • Produktionsreife Fehlerbehandlung

Für weitere fortgeschrittene Funktionen erkunden Sie unsere anderen Leitfäden:

Die IPFS.NINJA-API bietet alles, was Sie für Python-basierte IPFS-Anwendungen benötigen, ohne die Komplexität, eine eigene Infrastruktur zu betreiben.

Bereit zum Pinnen? Erstellen Sie ein kostenloses Konto — 50 Dateien, 1 GB Speicher, 2 GB Bandbreite/Monat. Keine Kreditkarte erforderlich.

Zurück zum Blog

Verwandte Artikel

Alle Artikel anzeigen »