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