diff --git a/cmd/swarm/main.go b/cmd/swarm/main.go index 731c300f8..47ed662d4 100644 --- a/cmd/swarm/main.go +++ b/cmd/swarm/main.go @@ -112,6 +112,14 @@ var ( Name: "defaultpath", Usage: "path to file served for empty url path (none)", } + SwarmUpFromStdinFlag = cli.BoolFlag{ + Name: "stdin", + Usage: "reads data to be uploaded from stdin", + } + SwarmUploadMimeType = cli.StringFlag{ + Name: "mime", + Usage: "force mime type", + } CorsStringFlag = cli.StringFlag{ Name: "corsdomain", Usage: "Domain on which to send Access-Control-Allow-Origin header (multiple domains can be supplied separated by a ',')", @@ -244,6 +252,8 @@ Cleans database of corrupted entries. SwarmRecursiveUploadFlag, SwarmWantManifestFlag, SwarmUploadDefaultPath, + SwarmUpFromStdinFlag, + SwarmUploadMimeType, } app.Flags = append(app.Flags, debug.Flags...) app.Before = func(ctx *cli.Context) error { diff --git a/cmd/swarm/upload.go b/cmd/swarm/upload.go index 696b907d2..46f10c4be 100644 --- a/cmd/swarm/upload.go +++ b/cmd/swarm/upload.go @@ -20,6 +20,8 @@ package main import ( "encoding/json" "fmt" + "io" + "io/ioutil" "os" "os/user" "path" @@ -31,21 +33,42 @@ import ( ) func upload(ctx *cli.Context) { + args := ctx.Args() var ( bzzapi = strings.TrimRight(ctx.GlobalString(SwarmApiFlag.Name), "/") recursive = ctx.GlobalBool(SwarmRecursiveUploadFlag.Name) wantManifest = ctx.GlobalBoolT(SwarmWantManifestFlag.Name) defaultPath = ctx.GlobalString(SwarmUploadDefaultPath.Name) + fromStdin = ctx.GlobalBool(SwarmUpFromStdinFlag.Name) + mimeType = ctx.GlobalString(SwarmUploadMimeType.Name) ) + + var client = swarm.NewClient(bzzapi) + var entry swarm.ManifestEntry + var file string + if len(args) != 1 { - utils.Fatalf("Need filename as the first and only argument") + if fromStdin { + tmp, err := ioutil.TempFile("", "swarm-stdin") + if err != nil { + utils.Fatalf("error create tempfile: %s", err) + } + defer os.Remove(tmp.Name()) + n, err := io.Copy(tmp, os.Stdin) + if err != nil { + utils.Fatalf("error copying stdin to tempfile: %s", err) + } else if n == 0 { + utils.Fatalf("error reading from stdin: zero length") + } + file = tmp.Name() + } else { + utils.Fatalf("Need filename as the first and only argument") + } + } else { + file = args[0] } - var ( - file = args[0] - client = swarm.NewClient(bzzapi) - ) fi, err := os.Stat(expandPath(file)) if err != nil { utils.Fatalf("Failed to stat file: %v", err) @@ -64,7 +87,7 @@ func upload(ctx *cli.Context) { fmt.Println(mhash) return } - entry, err := client.UploadFile(file, fi) + entry, err = client.UploadFile(file, fi, mimeType) if err != nil { utils.Fatalf("Upload failed: %v", err) } diff --git a/swarm/api/client/client.go b/swarm/api/client/client.go index 15e44f35d..ef5335be3 100644 --- a/swarm/api/client/client.go +++ b/swarm/api/client/client.go @@ -89,8 +89,32 @@ func (c *Client) UploadDirectory(dir string, defaultPath string) (string, error) return mhash, err } -func (c *Client) UploadFile(file string, fi os.FileInfo) (ManifestEntry, error) { +func (c *Client) UploadFile(file string, fi os.FileInfo, mimetype_hint string) (ManifestEntry, error) { + var mimetype string hash, err := c.uploadFileContent(file, fi) + if mimetype_hint != "" { + mimetype = mimetype_hint + log.Info("Mime type set by override", "mime", mimetype) + } else { + ext := filepath.Ext(file) + log.Info("Ext", "ext", ext, "file", file) + if ext != "" { + mimetype = mime.TypeByExtension(filepath.Ext(fi.Name())) + log.Info("Mime type set by fileextension", "mime", mimetype, "ext", filepath.Ext(file)) + } else { + f, err := os.Open(file) + if err == nil { + first512 := make([]byte, 512) + fread, _ := f.ReadAt(first512, 0) + if fread > 0 { + mimetype = http.DetectContentType(first512[:fread]) + log.Info("Mime type set by autodetection", "mime", mimetype) + } + } + f.Close() + } + + } m := ManifestEntry{ Hash: hash, ContentType: mime.TypeByExtension(filepath.Ext(fi.Name())),