1
mirror of https://github.com/rclone/rclone synced 2024-12-20 10:25:56 +01:00

rc: Add operations/uploadfile to upload a file through rc using encoding multipart/form-data

This commit is contained in:
Chaitanya Bankanhal 2020-06-12 11:34:30 +05:30 committed by Nick Craig-Wood
parent d0de39ebcd
commit fa43d02874
2 changed files with 59 additions and 0 deletions

View File

@ -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)
}

View File

@ -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