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 }