M storage/s3.go => storage/s3.go +20 -7
@@ 132,22 132,35 @@ func (s *S3Service) GetObject(ctx context.Context, path string) (*Object, error)
// PutObject uploads an object to Amazon S3 compat bucket, at prefix
func (s *S3Service) PutObject(ctx context.Context, path string, content io.Reader) error {
- var data bytes.Buffer
+ var (
+ data io.Reader
+ size int64
+ )
fullpath := pathutil.Join(s.Prefix, path)
meta := make(map[string]string)
if s.perm != "" {
meta["x-amz-acl"] = s.perm
}
- _, err := io.Copy(&data, content)
- if err != nil {
- return err
+
+ if sizer, ok := content.(ReadSizer); ok {
+ size = sizer.Size()
+ data = content
+ } else {
+ var bufData bytes.Buffer
+ _, err := io.Copy(&bufData, content)
+ if err != nil {
+ return err
+ }
+ data = &bufData
+ size = int64(bufData.Len())
}
- _, err = s.Client.PutObject(
+
+ _, err := s.Client.PutObject(
ctx,
s.Bucket,
fullpath,
- &data,
- int64(data.Len()),
+ data,
+ size,
minio.PutObjectOptions{UserMetadata: meta, ContentType: guessMimeType(path)},
)
return err
M storage/storage.go => storage/storage.go +25 -0
@@ 21,6 21,12 @@ type (
LastModified time.Time
}
+ // ObjectWrap is a simple type to implement the ReadSizer interface
+ ObjectWrap struct {
+ file io.Reader
+ size int64
+ }
+
// Service is a generic interface for storage backends
Service interface {
ListObjects(ctx context.Context, prefix string) ([]*Object, error)
@@ 28,6 34,13 @@ type (
PutObject(ctx context.Context, path string, content io.Reader) error
DeleteObject(ctx context.Context, path string) error
}
+
+ // ReadSizer is just a helper interface to determine content length, mainly for
+ // PutObject method of the Service interface
+ ReadSizer interface {
+ Read(p []byte) (n int, err error)
+ Size() int64
+ }
)
// HasExtension determines whether or not an object contains a file extension
@@ 69,3 82,15 @@ func guessMimeType(fname string) string {
}
return ctype
}
+
+func (o *ObjectWrap) Read(b []byte) (n int, err error) {
+ return o.file.Read(b)
+}
+
+func (o *ObjectWrap) Size() int64 {
+ return o.size
+}
+
+func NewObjectWrap(content io.Reader, size int64) *ObjectWrap {
+ return &ObjectWrap{content, size}
+}