Search code examples
pythonipfs

Pinning directory through Pinata API with python


I am trying to use pinata's API to pin a whole directory, as it is specified in their API documentation.

I found some python implementation as well, but that still doesn't seem to work for me.

Basically I am getting all the files from the directory and trying to include them in the post request.

all_files: tp.List[str] = get_all_files(filepath)            
files = {"file": [(file, open(file, "rb")) for file in all_files]}

response: requests.Response = requests.post(url=ipfs_url, files=files, headers=headers)

The error I get is the following:

ValueError: too many values to unpack (expected 4)

I additionally tried it with some hard coded values, but still no luck:

all_files = ['images/0.png', 'images/1.png', 'images/2.png']
files = {"file": [(file, open(file, "rb")) for file in all_files]}

response: requests.Response = requests.post(url=ipfs_url, files=files, headers=headers)

In this case however I got a different error:

TypeError: expected string or bytes-like object

Also as another try I tried to experiment with stuff like this:

files = (
    ("file", ("0.png", open('images/0.png', "rb"))),
    ("file", ("1.png", open('images/1.png', "rb")))
)

response: requests.Response = requests.post(url=ipfs_url, files=files, headers=headers)

In this case, Pinata could not recognize what I wanted and returned the following error:

{'error': 'More than one file and/or directory was provided for pinning.'}

Could someone give me some hints about what am I doing wrong? Thanks!

EDIT: Adding a full example to use:

import os
import requests
import typing as tp

def get_all_files(directory: str) -> tp.List[str]:
    """get a list of absolute paths to every file located in the directory"""
    paths: tp.List[str] = []
    for root, dirs, files_ in os.walk(os.path.abspath(directory)):        
        for file in files_:            
             paths.append(os.path.join(root, file))
    return paths
    
  
print("hello")
# Example 1
all_files: tp.List[str] = get_all_files("images")            
files = {"file": [(file, open(file, "rb")) for file in all_files]}

# Example 2
#all_files = ['images/0.png', 'images/1.png', 'images/2.png']
#files = {"file": [(file, open(file, "rb")) for file in all_files]}

# Example 3
#files = (
#    ("file", ("0.png", open('images/0.png', "rb"))),
#    ("file", ("1.png", open('images/1.png', "rb")))
#)

print ("Files used: \n")
print (files)

headers = {        
    'pinata_api_key': "",
    'pinata_secret_api_key': ""     
}   

ipfs_url = "https://api.pinata.cloud/pinning/pinFileToIPFS"

response: requests.Response = requests.post(url=ipfs_url, files=files, headers=headers)
print(response.json())

Solution

  • Okay, I managed to upload the whole directory with specifying the files like this:

    files = [
            ('file', ('images/0.png', open('images/0.png', "rb"))),
            ('file', ('images/1.png', open('images/1.png', "rb"))),
        ]
    

    So overall to gather all the files and upload them, I was able to use the following code:

    all_files: tp.List[str] = get_all_files(directory)            
    files = [('file', (file, open(file, "rb"))) for file in all_files]