github.com/sberex/go-sberex@v1.8.2-0.20181113200658-ed96ac38f7d7/cmd/swarm/upload.go (about)

     1  // This file is part of the go-sberex library. The go-sberex library is 
     2  // free software: you can redistribute it and/or modify it under the terms 
     3  // of the GNU Lesser General Public License as published by the Free 
     4  // Software Foundation, either version 3 of the License, or (at your option)
     5  // any later version.
     6  //
     7  // The go-sberex library is distributed in the hope that it will be useful, 
     8  // but WITHOUT ANY WARRANTY; without even the implied warranty of
     9  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 
    10  // General Public License <http://www.gnu.org/licenses/> for more details.
    11  
    12  // Command bzzup uploads files to the swarm HTTP API.
    13  package main
    14  
    15  import (
    16  	"errors"
    17  	"fmt"
    18  	"io"
    19  	"io/ioutil"
    20  	"mime"
    21  	"net/http"
    22  	"os"
    23  	"os/user"
    24  	"path"
    25  	"path/filepath"
    26  	"strings"
    27  
    28  	"github.com/Sberex/go-sberex/cmd/utils"
    29  	swarm "github.com/Sberex/go-sberex/swarm/api/client"
    30  	"gopkg.in/urfave/cli.v1"
    31  )
    32  
    33  func upload(ctx *cli.Context) {
    34  
    35  	args := ctx.Args()
    36  	var (
    37  		bzzapi       = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
    38  		recursive    = ctx.GlobalBool(SwarmRecursiveUploadFlag.Name)
    39  		wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
    40  		defaultPath  = ctx.GlobalString(SwarmUploadDefaultPath.Name)
    41  		fromStdin    = ctx.GlobalBool(SwarmUpFromStdinFlag.Name)
    42  		mimeType     = ctx.GlobalString(SwarmUploadMimeType.Name)
    43  		client       = swarm.NewClient(bzzapi)
    44  		file         string
    45  	)
    46  
    47  	if len(args) != 1 {
    48  		if fromStdin {
    49  			tmp, err := ioutil.TempFile("", "swarm-stdin")
    50  			if err != nil {
    51  				utils.Fatalf("error create tempfile: %s", err)
    52  			}
    53  			defer os.Remove(tmp.Name())
    54  			n, err := io.Copy(tmp, os.Stdin)
    55  			if err != nil {
    56  				utils.Fatalf("error copying stdin to tempfile: %s", err)
    57  			} else if n == 0 {
    58  				utils.Fatalf("error reading from stdin: zero length")
    59  			}
    60  			file = tmp.Name()
    61  		} else {
    62  			utils.Fatalf("Need filename as the first and only argument")
    63  		}
    64  	} else {
    65  		file = expandPath(args[0])
    66  	}
    67  
    68  	if !wantManifest {
    69  		f, err := swarm.Open(file)
    70  		if err != nil {
    71  			utils.Fatalf("Error opening file: %s", err)
    72  		}
    73  		defer f.Close()
    74  		hash, err := client.UploadRaw(f, f.Size)
    75  		if err != nil {
    76  			utils.Fatalf("Upload failed: %s", err)
    77  		}
    78  		fmt.Println(hash)
    79  		return
    80  	}
    81  
    82  	stat, err := os.Stat(file)
    83  	if err != nil {
    84  		utils.Fatalf("Error opening file: %s", err)
    85  	}
    86  
    87  	// define a function which either uploads a directory or single file
    88  	// based on the type of the file being uploaded
    89  	var doUpload func() (hash string, err error)
    90  	if stat.IsDir() {
    91  		doUpload = func() (string, error) {
    92  			if !recursive {
    93  				return "", errors.New("Argument is a directory and recursive upload is disabled")
    94  			}
    95  			return client.UploadDirectory(file, defaultPath, "")
    96  		}
    97  	} else {
    98  		doUpload = func() (string, error) {
    99  			f, err := swarm.Open(file)
   100  			if err != nil {
   101  				return "", fmt.Errorf("error opening file: %s", err)
   102  			}
   103  			defer f.Close()
   104  			if mimeType == "" {
   105  				mimeType = detectMimeType(file)
   106  			}
   107  			f.ContentType = mimeType
   108  			return client.Upload(f, "")
   109  		}
   110  	}
   111  	hash, err := doUpload()
   112  	if err != nil {
   113  		utils.Fatalf("Upload failed: %s", err)
   114  	}
   115  	fmt.Println(hash)
   116  }
   117  
   118  // Expands a file path
   119  // 1. replace tilde with users home dir
   120  // 2. expands embedded environment variables
   121  // 3. cleans the path, e.g. /a/b/../c -> /a/c
   122  // Note, it has limitations, e.g. ~someuser/tmp will not be expanded
   123  func expandPath(p string) string {
   124  	if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
   125  		if home := homeDir(); home != "" {
   126  			p = home + p[1:]
   127  		}
   128  	}
   129  	return path.Clean(os.ExpandEnv(p))
   130  }
   131  
   132  func homeDir() string {
   133  	if home := os.Getenv("HOME"); home != "" {
   134  		return home
   135  	}
   136  	if usr, err := user.Current(); err == nil {
   137  		return usr.HomeDir
   138  	}
   139  	return ""
   140  }
   141  
   142  func detectMimeType(file string) string {
   143  	if ext := filepath.Ext(file); ext != "" {
   144  		return mime.TypeByExtension(ext)
   145  	}
   146  	f, err := os.Open(file)
   147  	if err != nil {
   148  		return ""
   149  	}
   150  	defer f.Close()
   151  	buf := make([]byte, 512)
   152  	if n, _ := f.Read(buf); n > 0 {
   153  		return http.DetectContentType(buf)
   154  	}
   155  	return ""
   156  }