如何使用Python-Brownie脚本上传含元数据的文件夹至Pinata?
问题分析与解决方案
错误原因
你遇到的PermissionError是因为代码尝试将文件夹(C:\Users\acer\Desktop\Ciao)当作普通文件用Path.open()打开,操作系统不允许直接以读文件的方式打开文件夹,因此触发权限拒绝错误。
此外代码还有两处明显问题:
filepath.read()无效:filepath是字符串路径,不是文件对象,应该使用打开的文件指针fp来读取内容。filename是文件夹内所有文件的列表,但你直接将这个列表传给请求的files参数,而该参数需要单个文件名或每个文件对应的正确格式条目。
解决方案
方案1:逐个上传文件夹内的文件
如果需要单独上传每个文件,可使用以下代码:
import os import requests PINATA_BASE_URL = "https://api.pinata.cloud/" endpoint = "pinning/pinFileToIPFS" folder_path = "C:/Users/acer/Desktop/Ciao" headers = { "pinata_api_key": os.getenv("PINATA_API_KEY"), "pinata_secret_api_key": os.getenv("PINATA_API_SECRET"), } def upload_single_file(file_full_path): with open(file_full_path, "rb") as fp: file_name = os.path.basename(file_full_path) response = requests.post( PINATA_BASE_URL + endpoint, files={"file": (file_name, fp.read())}, headers=headers, ) print(f"已上传 {file_name}: {response.json()}") def main(): # 遍历文件夹内所有文件 for item in os.listdir(folder_path): full_path = os.path.join(folder_path, item) # 仅处理文件,跳过子文件夹 if os.path.isfile(full_path): upload_single_file(full_path) if __name__ == "__main__": main()
方案2:压缩文件夹后上传(保留目录结构)
如果需要保留原文件夹的结构上传到IPFS,可先将文件夹压缩为ZIP包再上传:
import os import zipfile import requests PINATA_BASE_URL = "https://api.pinata.cloud/" endpoint = "pinning/pinFileToIPFS" folder_path = "C:/Users/acer/Desktop/Ciao" zip_file_name = "Ciao.zip" headers = { "pinata_api_key": os.getenv("PINATA_API_KEY"), "pinata_secret_api_key": os.getenv("PINATA_API_SECRET"), } def zip_target_folder(folder_path, zip_name): with zipfile.ZipFile(zip_name, 'w', zipfile.ZIP_DEFLATED) as zip_handle: # 遍历文件夹所有内容,保留相对路径 for root, dirs, files in os.walk(folder_path): for file in files: file_full_path = os.path.join(root, file) zip_handle.write(file_full_path, os.path.relpath(file_full_path, folder_path)) def main(): # 生成压缩包 zip_target_folder(folder_path, zip_file_name) # 上传压缩包到Pinata with open(zip_file_name, "rb") as fp: response = requests.post( PINATA_BASE_URL + endpoint, files={"file": (zip_file_name, fp.read())}, headers=headers, ) print(response.json()) # 可选:上传完成后删除本地压缩包 os.remove(zip_file_name) if __name__ == "__main__": main()
方案3:使用Pinata SDK直接上传文件夹(更简洁)
如果愿意使用Pinata官方SDK,可以先安装:
pip install pinata-sdk
然后用以下代码直接上传文件夹:
import os from pinata import Pinata pinata = Pinata(api_key=os.getenv("PINATA_API_KEY"), api_secret=os.getenv("PINATA_API_SECRET")) response = pinata.pin_from_fs("C:/Users/acer/Desktop/Ciao") print(response)
内容的提问来源于stack exchange,提问作者Tulli
相关产品推荐
相关产品推荐

