github.com/TrueBlocks/trueblocks-core/src/apps/chifra@v0.0.0-20241022031540-b362680128f7/pkg/pinning/pin_file_remotely.go (about)

     1  // IPFS Client code https://pkg.go.dev/github.com/ipfs/go-ipfs-http-client for pinning directly
     2  
     3  package pinning
     4  
     5  import (
     6  	"encoding/json"
     7  	"fmt"
     8  	"io"
     9  	"mime/multipart"
    10  	"net/http"
    11  	"os"
    12  	fp "path/filepath"
    13  	"time"
    14  
    15  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/base"
    16  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/config"
    17  	"github.com/TrueBlocks/trueblocks-core/src/apps/chifra/pkg/file"
    18  )
    19  
    20  // pinFileRemotely pins a file remotely to the pinning service
    21  func (s *Service) pinFileRemotely(chain, filepath string) (base.IpfsHash, error) {
    22  	if s.HeaderFunc == nil {
    23  		return "", fmt.Errorf("header function is nil")
    24  	}
    25  
    26  	ff, err := os.OpenFile(filepath, os.O_RDONLY, 0)
    27  	if err != nil {
    28  		return "", err
    29  	}
    30  	defer ff.Close()
    31  
    32  	r, w := io.Pipe()
    33  	m := multipart.NewWriter(w)
    34  
    35  	go func() {
    36  		defer w.Close()
    37  		defer m.Close()
    38  
    39  		part, err := m.CreateFormFile("file", fp.Base(ff.Name()))
    40  		if err != nil {
    41  			return
    42  		}
    43  
    44  		if _, err = io.Copy(part, ff); err != nil {
    45  			return
    46  		}
    47  	}()
    48  
    49  	fileSize := file.FileSize(filepath)
    50  	timeout := time.Duration(((fileSize / (50 * 1024 * 1024)) + 1) * 30) // 30 seconds per 50MB
    51  	client := &http.Client{
    52  		Timeout: timeout * time.Second,
    53  	}
    54  
    55  	req, err := http.NewRequest(http.MethodPost, config.GetPinning().RemotePinUrl, r)
    56  	if err != nil {
    57  		return "", err
    58  	}
    59  
    60  	if s.HeaderFunc != nil {
    61  		headers := s.HeaderFunc(s, m.FormDataContentType())
    62  		for key, value := range headers {
    63  			req.Header.Add(key, value)
    64  		}
    65  	}
    66  
    67  	resp, err := client.Do(req)
    68  	if err != nil {
    69  		return "", err
    70  	}
    71  	defer resp.Body.Close()
    72  
    73  	data, err := io.ReadAll(resp.Body)
    74  	if err != nil {
    75  		return "", err
    76  	}
    77  
    78  	var dat = struct {
    79  		IpfsHash string
    80  		PinSize  int64
    81  		Date     string
    82  	}{}
    83  
    84  	if err := json.Unmarshal(data, &dat); err != nil {
    85  		return "", err
    86  	}
    87  	return base.IpfsHash(dat.IpfsHash), nil
    88  }