diff --git a/go.mod b/go.mod index e0758067..fd2c5847 100644 --- a/go.mod +++ b/go.mod @@ -7,6 +7,7 @@ require ( github.com/aws/aws-sdk-go v1.44.144 github.com/dgraph-io/badger v1.6.2 github.com/eduncan911/podcast v1.4.2 + github.com/gabriel-vasile/mimetype v1.4.10 github.com/gilliek/go-opml v1.0.0 github.com/golang/mock v1.6.0 github.com/hashicorp/go-multierror v1.1.1 diff --git a/go.sum b/go.sum index cd3ef759..3eb60938 100644 --- a/go.sum +++ b/go.sum @@ -36,6 +36,8 @@ github.com/eduncan911/podcast v1.4.2/go.mod h1:mSxiK1z5KeNO0YFaQ3ElJlUZbbDV9dA7R github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gabriel-vasile/mimetype v1.4.10 h1:zyueNbySn/z8mJZHLt6IPw0KoZsiQNszIpU+bX4+ZK0= +github.com/gabriel-vasile/mimetype v1.4.10/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= github.com/gilliek/go-opml v1.0.0 h1:X8xVjtySRXU/x6KvaiXkn7OV3a4DHqxY8Rpv6U/JvCY= github.com/gilliek/go-opml v1.0.0/go.mod h1:fOxmtlzyBvUjU6bjpdjyxCGlWz+pgtAHrHf/xRZl3lk= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= diff --git a/pkg/fs/s3.go b/pkg/fs/s3.go index 6f2b3828..1337e161 100644 --- a/pkg/fs/s3.go +++ b/pkg/fs/s3.go @@ -1,6 +1,7 @@ package fs import ( + "bytes" "context" "io" "net/http" @@ -13,6 +14,7 @@ import ( "github.com/aws/aws-sdk-go/service/s3" "github.com/aws/aws-sdk-go/service/s3/s3iface" "github.com/aws/aws-sdk-go/service/s3/s3manager" + "github.com/gabriel-vasile/mimetype" "github.com/pkg/errors" log "github.com/sirupsen/logrus" ) @@ -79,12 +81,23 @@ func (s *S3) Create(ctx context.Context, name string, reader io.Reader) (int64, key := s.buildKey(name) logger := log.WithField("key", key) + // Detect MIME type from the first 512 bytes and then replay them with the rest of the stream. + buf := make([]byte, 512) + n, err := io.ReadFull(reader, buf) + if err != nil && err != io.EOF && err != io.ErrUnexpectedEOF { + return 0, errors.Wrap(err, "failed to read file header for MIME detection") + } + head := buf[:n] + m := mimetype.Detect(head) + body := io.MultiReader(bytes.NewReader(head), reader) + logger.Infof("uploading file to %s", s.bucket) - r := &readerWithN{Reader: reader} - _, err := s.uploader.UploadWithContext(ctx, &s3manager.UploadInput{ - Bucket: &s.bucket, - Key: &key, - Body: r, + r := &readerWithN{Reader: body} + _, err = s.uploader.UploadWithContext(ctx, &s3manager.UploadInput{ + Body: r, + Bucket: &s.bucket, + ContentType: aws.String(m.String()), + Key: &key, }) if err != nil { return 0, errors.Wrap(err, "failed to upload file")