github.com/linapex/ethereum-go-chinese@v0.0.0-20190316121929-f8b7a73c3fa1/cmd/swarm/upload.go (about)

     1  
     2  //<developer>
     3  //    <name>linapex 曹一峰</name>
     4  //    <email>linapex@163.com</email>
     5  //    <wx>superexc</wx>
     6  //    <qqgroup>128148617</qqgroup>
     7  //    <url>https://jsq.ink</url>
     8  //    <role>pku engineer</role>
     9  //    <date>2019-03-16 19:16:33</date>
    10  //</624450072049881088>
    11  
    12  
    13  //命令bzzup将文件上载到Swarm HTTP API。
    14  package main
    15  
    16  import (
    17  	"errors"
    18  	"fmt"
    19  	"io"
    20  	"io/ioutil"
    21  	"os"
    22  	"os/user"
    23  	"path"
    24  	"path/filepath"
    25  	"strconv"
    26  	"strings"
    27  
    28  	"github.com/ethereum/go-ethereum/log"
    29  	swarm "github.com/ethereum/go-ethereum/swarm/api/client"
    30  
    31  	"github.com/ethereum/go-ethereum/cmd/utils"
    32  	"gopkg.in/urfave/cli.v1"
    33  )
    34  
    35  var upCommand = cli.Command{
    36  	Action:             upload,
    37  	CustomHelpTemplate: helpTemplate,
    38  	Name:               "up",
    39  	Usage:              "uploads a file or directory to swarm using the HTTP API",
    40  	ArgsUsage:          "<file>",
    41  	Flags:              []cli.Flag{SwarmEncryptedFlag},
    42  	Description:        "uploads a file or directory to swarm using the HTTP API and prints the root hash",
    43  }
    44  
    45  func upload(ctx *cli.Context) {
    46  	args := ctx.Args()
    47  	var (
    48  		bzzapi          = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/")
    49  		recursive       = ctx.GlobalBool(SwarmRecursiveFlag.Name)
    50  		wantManifest    = ctx.GlobalBoolT(SwarmWantManifestFlag.Name)
    51  		defaultPath     = ctx.GlobalString(SwarmUploadDefaultPath.Name)
    52  		fromStdin       = ctx.GlobalBool(SwarmUpFromStdinFlag.Name)
    53  		mimeType        = ctx.GlobalString(SwarmUploadMimeType.Name)
    54  		client          = swarm.NewClient(bzzapi)
    55  		toEncrypt       = ctx.Bool(SwarmEncryptedFlag.Name)
    56  		autoDefaultPath = false
    57  		file            string
    58  	)
    59  	if autoDefaultPathString := os.Getenv(SWARM_AUTO_DEFAULTPATH); autoDefaultPathString != "" {
    60  		b, err := strconv.ParseBool(autoDefaultPathString)
    61  		if err != nil {
    62  			utils.Fatalf("invalid environment variable %s: %v", SWARM_AUTO_DEFAULTPATH, err)
    63  		}
    64  		autoDefaultPath = b
    65  	}
    66  	if len(args) != 1 {
    67  		if fromStdin {
    68  			tmp, err := ioutil.TempFile("", "swarm-stdin")
    69  			if err != nil {
    70  				utils.Fatalf("error create tempfile: %s", err)
    71  			}
    72  			defer os.Remove(tmp.Name())
    73  			n, err := io.Copy(tmp, os.Stdin)
    74  			if err != nil {
    75  				utils.Fatalf("error copying stdin to tempfile: %s", err)
    76  			} else if n == 0 {
    77  				utils.Fatalf("error reading from stdin: zero length")
    78  			}
    79  			file = tmp.Name()
    80  		} else {
    81  			utils.Fatalf("Need filename as the first and only argument")
    82  		}
    83  	} else {
    84  		file = expandPath(args[0])
    85  	}
    86  
    87  	if !wantManifest {
    88  		f, err := swarm.Open(file)
    89  		if err != nil {
    90  			utils.Fatalf("Error opening file: %s", err)
    91  		}
    92  		defer f.Close()
    93  		hash, err := client.UploadRaw(f, f.Size, toEncrypt)
    94  		if err != nil {
    95  			utils.Fatalf("Upload failed: %s", err)
    96  		}
    97  		fmt.Println(hash)
    98  		return
    99  	}
   100  
   101  	stat, err := os.Stat(file)
   102  	if err != nil {
   103  		utils.Fatalf("Error opening file: %s", err)
   104  	}
   105  
   106  //定义上载目录或单个文件的函数
   107  //根据上传文件的类型
   108  	var doUpload func() (hash string, err error)
   109  	if stat.IsDir() {
   110  		doUpload = func() (string, error) {
   111  			if !recursive {
   112  				return "", errors.New("Argument is a directory and recursive upload is disabled")
   113  			}
   114  			if autoDefaultPath && defaultPath == "" {
   115  				defaultEntryCandidate := path.Join(file, "index.html")
   116  				log.Debug("trying to find default path", "path", defaultEntryCandidate)
   117  				defaultEntryStat, err := os.Stat(defaultEntryCandidate)
   118  				if err == nil && !defaultEntryStat.IsDir() {
   119  					log.Debug("setting auto detected default path", "path", defaultEntryCandidate)
   120  					defaultPath = defaultEntryCandidate
   121  				}
   122  			}
   123  			if defaultPath != "" {
   124  //构造绝对默认路径
   125  				absDefaultPath, _ := filepath.Abs(defaultPath)
   126  				absFile, _ := filepath.Abs(file)
   127  //确保绝对目录只以一个“/”结尾
   128  //从绝对默认路径修剪它并获取相对默认路径
   129  				absFile = strings.TrimRight(absFile, "/") + "/"
   130  				if absDefaultPath != "" && absFile != "" && strings.HasPrefix(absDefaultPath, absFile) {
   131  					defaultPath = strings.TrimPrefix(absDefaultPath, absFile)
   132  				}
   133  			}
   134  			return client.UploadDirectory(file, defaultPath, "", toEncrypt)
   135  		}
   136  	} else {
   137  		doUpload = func() (string, error) {
   138  			f, err := swarm.Open(file)
   139  			if err != nil {
   140  				return "", fmt.Errorf("error opening file: %s", err)
   141  			}
   142  			defer f.Close()
   143  			if mimeType != "" {
   144  				f.ContentType = mimeType
   145  			}
   146  			return client.Upload(f, "", toEncrypt)
   147  		}
   148  	}
   149  	hash, err := doUpload()
   150  	if err != nil {
   151  		utils.Fatalf("Upload failed: %s", err)
   152  	}
   153  	fmt.Println(hash)
   154  }
   155  
   156  //展开文件路径
   157  //1。用用户主目录替换tilde
   158  //2。扩展嵌入的环境变量
   159  //三。清理路径,例如/a/b/。/c->/a/c
   160  //注意,它有局限性,例如~someuser/tmp将不会扩展
   161  func expandPath(p string) string {
   162  	if i := strings.Index(p, ":"); i > 0 {
   163  		return p
   164  	}
   165  	if i := strings.Index(p, "@"); i > 0 {
   166  		return p
   167  	}
   168  	if strings.HasPrefix(p, "~/") || strings.HasPrefix(p, "~\\") {
   169  		if home := homeDir(); home != "" {
   170  			p = home + p[1:]
   171  		}
   172  	}
   173  	return path.Clean(os.ExpandEnv(p))
   174  }
   175  
   176  func homeDir() string {
   177  	if home := os.Getenv("HOME"); home != "" {
   178  		return home
   179  	}
   180  	if usr, err := user.Current(); err == nil {
   181  		return usr.HomeDir
   182  	}
   183  	return ""
   184  }
   185