From fa43d0287429994e8640035191a3afea861e8700 Mon Sep 17 00:00:00 2001 From: Chaitanya Bankanhal Date: Fri, 12 Jun 2020 11:34:30 +0530 Subject: [PATCH] rc: Add operations/uploadfile to upload a file through rc using encoding multipart/form-data --- fs/operations/rc.go | 41 +++++++++++++++++++++++++++++++++++++++++ fs/rc/params.go | 18 ++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/fs/operations/rc.go b/fs/operations/rc.go index 5bc0c7033..672dfc31d 100644 --- a/fs/operations/rc.go +++ b/fs/operations/rc.go @@ -2,7 +2,12 @@ package operations import ( "context" + "io" + "mime" + "mime/multipart" + "net/http" "strings" + "time" "github.com/pkg/errors" "github.com/rclone/rclone/fs" @@ -151,6 +156,7 @@ func init() { {name: "delete", title: "Remove files in the path", noRemote: true}, {name: "deletefile", title: "Remove the single file pointed to"}, {name: "copyurl", title: "Copy the URL to the object", help: "- url - string, URL to read from\n - autoFilename - boolean, set to true to retrieve destination file name from url"}, + {name: "uploadfile", title: "Upload file using multiform/form-data", help: "- each part in body represents a file to be uploaded", needsRequest: true}, {name: "cleanup", title: "Remove trashed files in the remote or path", noRemote: true}, } { op := op @@ -221,6 +227,41 @@ func rcSingleCommand(ctx context.Context, in rc.Params, name string, noRemote bo _, err = CopyURL(ctx, f, remote, url, autoFilename, noClobber) return nil, err + case "uploadfile": + + var request *http.Request + request, err := in.GetHTTPRequest() + + if err != nil { + return nil, err + } + + contentType := request.Header.Get("Content-Type") + mediaType, params, err := mime.ParseMediaType(contentType) + if err != nil { + return nil, err + } + + if strings.HasPrefix(mediaType, "multipart/") { + mr := multipart.NewReader(request.Body, params["boundary"]) + for { + p, err := mr.NextPart() + if err == io.EOF { + return nil, nil + } + if err != nil { + return nil, err + } + if p.FileName() != "" { + obj, err := Rcat(ctx, f, p.FileName(), p, time.Now()) + if err != nil { + return nil, err + } + fs.Debugf(obj, "Upload Succeeded") + } + } + } + return nil, nil case "cleanup": return nil, CleanUp(ctx, f) } diff --git a/fs/rc/params.go b/fs/rc/params.go index 415cb4e32..dd0d57317 100644 --- a/fs/rc/params.go +++ b/fs/rc/params.go @@ -6,6 +6,7 @@ import ( "encoding/json" "fmt" "math" + "net/http" "strconv" "time" @@ -90,6 +91,23 @@ func (p Params) Get(key string) (interface{}, error) { return value, nil } +// GetHTTPRequest gets a http.Request parameter associated with the request with the key "HttpRequest" +// +// If the parameter isn't found then error will be of type +// ErrParamNotFound and the returned value will be nil. +func (p Params) GetHTTPRequest() (*http.Request, error) { + key := "_request" + value, err := p.Get(key) + if err != nil { + return nil, err + } + request, ok := value.(*http.Request) + if !ok { + return nil, ErrParamInvalid{errors.Errorf("expecting http.request value for key %q (was %T)", key, value)} + } + return request, nil +} + // GetString gets a string parameter from the input // // If the parameter isn't found then error will be of type