You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Go语言中使用Pinata Submarine功能固定目录

如何修改Go代码实现Pinata Submarine的目录固定

我目前通过Go语言使用Pinata Submarine功能向私有网关上传单个文件,功能正常,但需要改为固定整个目录。根据官方文档,目录固定与文件固定操作基本一致,核心区别是需要传入文件数组,并为每个文件指定相对目录路径。以下是具体的代码修改方案:

核心修改点

  • 遍历目标目录:使用filepath.Walk遍历目录下所有文件,跳过目录本身
  • 指定相对路径:为每个文件计算相对于根目录的路径,作为表单上传时的文件名参数,确保目录结构被保留
  • 调整目录参数:将wrapWithDirectory字段设为"true",告知Pinata将文件组织为目录结构
  • 优化错误处理:不再忽略表单字段写入的错误,增加代码健壮性

修改后的完整代码

package ipfs

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
)

func PinDirectory(rootDir string, dirName string) {
	// Pinata Submarine 目录固定接口地址
	url := "https://managed.mypinata.cloud/api/v1/content"
	method := "POST"

	payload := &bytes.Buffer{}
	writer := multipart.NewWriter(payload)

	// 遍历目录下所有文件
	err := filepath.Walk(rootDir, func(filePath string, info os.FileInfo, err error) error {
		if err != nil {
			return err
		}
		// 跳过目录,只处理文件
		if info.IsDir() {
			return nil
		}

		// 计算文件相对于根目录的路径,作为目录结构中的路径
		relPath, err := filepath.Rel(rootDir, filePath)
		if err != nil {
			return err
		}

		// 打开文件
		file, err := os.Open(filePath)
		if err != nil {
			return err
		}
		defer file.Close()

		// 创建表单文件字段,使用相对路径作为文件名
		part, err := writer.CreateFormFile("files", relPath)
		if err != nil {
			return err
		}
		_, err = io.Copy(part, file)
		return err
	})

	if err != nil {
		fmt.Println("遍历目录或添加文件失败:", err)
		return
	}

	// 设置目录固定的附加参数
	if err := writer.WriteField("name", dirName); err != nil {
		fmt.Println("写入name字段失败:", err)
		return
	}
	if err := writer.WriteField("metadata", "{\"keyvalues\": { \"app\": \"...\" }}"); err != nil {
		fmt.Println("写入metadata字段失败:", err)
		return
	}
	// 开启目录包装,将上传的文件组织为目录结构
	if err := writer.WriteField("wrapWithDirectory", "true"); err != nil {
		fmt.Println("写入wrapWithDirectory字段失败:", err)
		return
	}
	if err := writer.WriteField("pinToIPFS", "false"); err != nil {
		fmt.Println("写入pinToIPFS字段失败:", err)
		return
	}

	// 关闭multipart writer
	if err := writer.Close(); err != nil {
		fmt.Println("关闭writer失败:", err)
		return
	}

	// 创建HTTP请求
	client := &http.Client{}
	req, err := http.NewRequest(method, url, payload)
	if err != nil {
		fmt.Println("创建请求失败:", err)
		return
	}

	// 设置Submarine密钥
	req.Header.Add("x-api-key", env.GetEnv["SUBMARINE_KEY"])
	// 设置表单内容类型
	req.Header.Set("Content-Type", writer.FormDataContentType())

	// 发送请求
	res, err := client.Do(req)
	if err != nil {
		fmt.Println("发送请求失败:", err)
		return
	}
	defer res.Body.Close()

	// 读取响应
	body, err := ioutil.ReadAll(res.Body)
	if err != nil {
		fmt.Println("读取响应失败:", err)
		return
	}
	fmt.Println("响应结果:", string(body))
}

代码说明

  • 目录遍历:filepath.Walk会递归遍历目标目录下的所有文件,自动跳过目录节点,只处理文件类型
  • 相对路径:filepath.Rel计算出的相对路径会作为文件在Pinata目录中的位置,确保上传后目录结构与本地完全一致
  • wrapWithDirectory:设为true是实现目录固定的关键,Pinata会根据每个文件的相对路径自动构建对应的目录结构
  • 错误处理:新增了对各个步骤的错误检查,避免因忽略错误导致的隐性问题

内容的提问来源于stack exchange,提问作者mev

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 10:25:20