diff options
| author | Stefan Majewsky <majewsky@gmx.net> | 2018-02-19 15:03:56 +0100 |
|---|---|---|
| committer | Stefan Majewsky <majewsky@gmx.net> | 2018-02-19 15:03:56 +0100 |
| commit | 502acc3c73e789e856a17b878889db4356fe898c (patch) | |
| tree | f3d48ed5d6dd950bc2c3c4a9e2a6cc670a7c8034 | |
| parent | 1a84987c7e28094f4e65bfb0fa03fdf5059ef6cc (diff) | |
| download | go-schwift-502acc3c73e789e856a17b878889db4356fe898c.tar.gz | |
add Object.Download(), DownloadedObject
| -rw-r--r-- | download.go | 83 | ||||
| -rw-r--r-- | object.go | 32 |
2 files changed, 114 insertions, 1 deletions
diff --git a/download.go b/download.go new file mode 100644 index 0000000..6515bbf --- /dev/null +++ b/download.go @@ -0,0 +1,83 @@ +/****************************************************************************** +* +* Copyright 2018 Stefan Majewsky <majewsky@gmx.net> +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +* +******************************************************************************/ + +package schwift + +import ( + "io" + "io/ioutil" +) + +//DownloadedObject is returned by Object.Download(). It wraps the io.ReadCloser +//from http.Response.Body with convenience methods for collecting the contents +//into a byte slice or string. +// +// var obj *swift.Object +// +// //Do NOT do this! +// reader, err := obj.Download(nil, nil).AsReadCloser() +// bytes, err := ioutil.ReadAll(reader) +// err := reader.Close() +// str := string(bytes) +// +// //Do this instead: +// str, err := obj.Download(nil, nil).AsString() +// +//Since the AsByteSlice and AsString method consume only the unread portion of +//the ReadCloser, and since they drain the ReadCloser irreversibly, the +//idiomatic way of using DownloadedObject is to call one of its members +//immediately, without storing the DownloadedObject instance in a variable +//first. +// +// var obj *swift.Object +// +// //Do NOT do this! +// downloaded := obj.Download(nil, nil) +// reader, err := downloaded.AsReadCloser() +// +// //Do this instead: +// reader, err := obj.Download(nil, nil).AsReadCloser() +type DownloadedObject struct { + r io.ReadCloser + err error +} + +//AsReadCloser returns an io.ReadCloser containing the contents of the +//downloaded object. +func (o DownloadedObject) AsReadCloser() (io.ReadCloser, error) { + return o.r, o.err +} + +//AsByteSlice collects the contents of this downloaded object into a byte slice. +func (o DownloadedObject) AsByteSlice() ([]byte, error) { + if o.err != nil { + return nil, o.err + } + slice, err := ioutil.ReadAll(o.r) + closeErr := o.r.Close() + if err == nil { + err = closeErr + } + return slice, closeErr +} + +//AsString collects the contents of this downloaded object into a string. +func (o DownloadedObject) AsString() (string, error) { + slice, err := o.AsByteSlice() + return string(slice), err +} @@ -262,5 +262,35 @@ func (o *Object) Invalidate() { o.headers = nil } -//TODO Object.Copy(), Object.Move(), Object.Download() +//Download retrieves the object's contents using a GET request. This returns a +//helper object which allows you to select whether you want an io.ReadCloser +//for reading the object contents progressively, or whether you want the object +//contents collected into a byte slice or string. +// +// reader, err := object.Download(nil, nil).AsReadCloser() +// +// buf, err := object.Download(nil, nil).AsByteSlice() +// +// str, err := object.Download(nil, nil).AsString() +// +func (o *Object) Download(headers ObjectHeaders, opts *RequestOptions) DownloadedObject { + resp, err := Request{ + Method: "GET", + ContainerName: o.c.name, + ObjectName: o.name, + Headers: headersToHTTP(headers), + Options: opts, + ExpectStatusCodes: []int{200}, + }.Do(o.c.a.client) + if err == nil { + headers := ObjectHeaders(headersFromHTTP(resp.Header)) + err = headers.Validate() + if err == nil { + o.headers = &headers + } + } + return DownloadedObject{resp.Body, err} +} + +//TODO Object.Copy(), Object.Move() //TODO provide a companion to Object.Upload() to connect it with content-generating functions where an io.Writer needs to be given |
