Skip to content

Instantly share code, notes, and snippets.

@mig5
Last active November 25, 2022 12:03
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mig5/422d5264e591ee7ff22236045b916c1f to your computer and use it in GitHub Desktop.
Save mig5/422d5264e591ee7ff22236045b916c1f to your computer and use it in GitHub Desktop.
A PoC showing how to publish a folder containing files to IPFS via Python using requests module
#!/usr/bin/env python3
# This code is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The author
# accepts no responsibility for its use, of which you do so at
# your own risk.
import json
import requests
from pathlib import Path
# Directory we want to publish
directory = "my-files"
# Read the first file, which is already inside that directory
file1 = f"{directory}/file1.txt"
p = Path(file1)
with p.open("rb") as fp:
file1_bytes = fp.read()
file1_name = p.name
file1_absolute_escaped = f"{directory}%2F{file1_name}"
# Read the second file
file2 = f"{directory}/file2.txt"
p = Path(file2)
with p.open("rb") as fp:
file2_bytes = fp.read()
file2_name = p.name
file2_absolute_escaped = f"{directory}%2F{file2_name}"
# Construct our files payload for the POST request to the IPFS API.
# Note how we use the absolute 'escaped' folder+file names for
# the file info. This is important for the IPFS API to understand that
# these files are 'inside' a directory. Notice that the directory doesn't
# explicitly get added, it is inferred from that path.
folder_and_files = {
file1_name: (
file1_absolute_escaped,
file1_bytes,
"application/octet-stream",
{"filename": file1_absolute_escaped},
),
file2_name: (
file2_absolute_escaped,
file2_bytes,
"application/octet-stream",
{"filename": file2_absolute_escaped},
),
}
# IPFS API endpoint
url = "http://127.0.0.1:5001/api/v0"
# Post the request to the IPFS API
response = requests.post(f"{url}/add", files=folder_and_files)
# The response contains a list of Name/Hash/Size attributes
# for each file, separated by a new line, but it's not a JSON blob
# apparently.
#
# It will look something like this:
#
# ['{"Name":"my-files/file1.txt","Hash":"QmZLRFWaz9Kypt2ACNMDzA5uzACDRiCqwdkNSP1UZsu56D","Size":"11"}',
# '{"Name":"my-files/file2.txt","Hash":"QmfTitKrVzFGbLCG2KaxBg5UMo6F2iYxsQCeC2er59cFTU","Size":"11"}',
# '{"Name":"my-files","Hash":"QmVRFp9xNPRLXXe4qXTwDx5sG3Wm6Y6jcbRJnv7u8EZcQu","Size":"128"}',
# '']
#
# It's the Hash of the directory that we want to point our IPNS
# ID at, so that our IPNS ID always points at the latest version.
ipfs_response = response.text.split("\n")
for item in ipfs_response:
j = json.loads(item)
if j["Name"] == directory:
ipfs_hash = j["Hash"]
# Point our IPNS at the directory's hash
response = requests.post(f"{url}/name/publish?arg={ipfs_hash}")
break
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment