Add s3 backend
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
nemunaire 2022-09-04 23:15:16 +02:00
parent d4764ce485
commit f1d98b605f
3 changed files with 257 additions and 0 deletions

239
backend_s3.go Normal file
View File

@ -0,0 +1,239 @@
package main
import (
"bytes"
"fmt"
"image"
"image/jpeg"
"io"
"log"
"net/http"
"path"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/s3"
"github.com/aws/aws-sdk-go/service/s3/s3manager"
)
func init() {
existing_backends = append(existing_backends, "s3")
}
type S3FileBackend struct {
Endpoint string
Region string
Bucket string
AccessKey string
SecretKey string
PathStyle bool
BaseDir string
}
func (l *S3FileBackend) getPath(box, name string) string {
if l.BaseDir == "" {
return path.Join(box, name+".jpg")
} else {
return path.Join(l.BaseDir, box, name+".jpg")
}
}
func (l *S3FileBackend) newSession() (*session.Session, error) {
return session.NewSession(&aws.Config{
Credentials: credentials.NewStaticCredentials(l.AccessKey, l.SecretKey, ""),
Endpoint: &l.Endpoint,
Region: &l.Region,
S3ForcePathStyle: &l.PathStyle,
})
}
func (l *S3FileBackend) DeletePicture(box, name string) error {
s, err := l.newSession()
if err != nil {
return err
}
log.Println(l.getPath(box, name))
input := &s3.DeleteObjectsInput{
Bucket: aws.String(l.Bucket),
Delete: &s3.Delete{
Objects: []*s3.ObjectIdentifier{
{
Key: aws.String(l.getPath(box, name)),
},
},
},
}
_, err = s3.New(s).DeleteObjects(input)
return err
}
func (l *S3FileBackend) ServeFile() http.Handler {
return l
}
func (l *S3FileBackend) ServeHTTP(w http.ResponseWriter, r *http.Request) {
s, err := l.newSession()
if err != nil {
return
}
result, err := s3.New(s).GetObject(&s3.GetObjectInput{
Bucket: aws.String(l.Bucket),
Key: aws.String(r.URL.Path),
})
if err != nil {
return
}
io.Copy(w, result.Body)
}
func (l *S3FileBackend) createPictureInfo(local_path, name string, file *s3.Object) *Picture {
return &Picture{
local_path, // Path
name, // Basename
name[:len(name)-len(path.Ext(name))], // Sanitized filename
*file.LastModified, // UploadTime
}
}
func (l *S3FileBackend) GetPicture(box, name string, w io.Writer) error {
s, err := l.newSession()
if err != nil {
return err
}
s3_path := l.getPath(box, name)
input := &s3.GetObjectInput{
Bucket: aws.String(l.Bucket),
Key: aws.String(s3_path),
}
result, err := s3.New(s).GetObject(input)
if err != nil {
return err
}
_, err = io.Copy(w, result.Body)
return err
}
func (l *S3FileBackend) GetPictureInfo(box, name string) (*Picture, error) {
s, err := l.newSession()
if err != nil {
return nil, err
}
input := &s3.ListObjectsInput{
Bucket: aws.String(l.Bucket),
Prefix: aws.String(l.getPath(box, name)),
}
result, err := s3.New(s).ListObjects(input)
if err != nil {
return nil, err
}
var pictures []*Picture
for _, file := range result.Contents {
pictures = append(pictures, l.createPictureInfo(*file.Key, path.Base(*file.Key), file))
break
}
if len(pictures) == 0 {
return nil, fmt.Errorf("Object not found")
}
return pictures[0], nil
}
func (l *S3FileBackend) ListPictures(box string) ([]*Picture, error) {
s, err := l.newSession()
if err != nil {
return nil, err
}
input := &s3.ListObjectsInput{
Bucket: aws.String(l.Bucket),
}
if l.BaseDir == "" {
input.Prefix = aws.String(box)
} else {
input.Prefix = aws.String(path.Join(l.BaseDir, box))
}
result, err := s3.New(s).ListObjects(input)
if err != nil {
return nil, err
}
pictures := make([]*Picture, 0)
for _, file := range result.Contents {
pictures = append(pictures, l.createPictureInfo(path.Join(box, *file.Key), path.Base(*file.Key), file))
}
return pictures, nil
}
func (l *S3FileBackend) MovePicture(box_from, box_to, name string) error {
s, err := l.newSession()
if err != nil {
return err
}
log.Println(l.getPath(box_from, name), l.getPath(box_to, name))
_, err = s3.New(s).CopyObject(&s3.CopyObjectInput{
Bucket: aws.String(l.Bucket),
CopySource: aws.String(path.Join("", l.Bucket, l.getPath(box_from, name))),
Key: aws.String(l.getPath(box_to, name)),
})
if err != nil {
return err
}
log.Println(l.getPath(box_from, name))
input := &s3.DeleteObjectsInput{
Bucket: aws.String(l.Bucket),
Delete: &s3.Delete{
Objects: []*s3.ObjectIdentifier{
{
Key: aws.String(l.getPath(box_from, name)),
},
},
},
}
_, err = s3.New(s).DeleteObjects(input)
return err
}
func (l *S3FileBackend) PutPicture(box, name string, img *image.Image) error {
s, err := l.newSession()
if err != nil {
return err
}
bbuf := new(bytes.Buffer)
err = jpeg.Encode(bbuf, *img, nil)
if err != nil {
return err
}
_, err = s3manager.NewUploader(s).Upload(&s3manager.UploadInput{
Bucket: aws.String(l.Bucket),
ACL: aws.String("public-read"),
Key: aws.String(l.getPath(box, name)),
Body: bbuf,
})
return err
}

1
go.mod
View File

@ -3,6 +3,7 @@ module git.nemunai.re/youp0m
go 1.16
require (
github.com/aws/aws-sdk-go v1.44.91
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b
)

17
go.sum
View File

@ -1,4 +1,21 @@
github.com/aws/aws-sdk-go v1.44.91 h1:SRWmuX7PTyhBdLuvSfM7KWrWISJsrRsUPcFDSFduRxY=
github.com/aws/aws-sdk-go v1.44.91/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/jmespath/go-jmespath v0.4.0 h1:BEgLn5cpjn8UN1mAw4NjwDrS35OdebyEtFe+9YPoQUg=
github.com/jmespath/go-jmespath v0.4.0/go.mod h1:T8mJZnbsbmF+m6zOOFylbeCJqk5+pHWvzYPziyZiYoo=
github.com/jmespath/go-jmespath/internal/testify v1.5.1/go.mod h1:L3OGu8Wl2/fWfCI6z80xFu9LTZmf1ZRjMHUOPmWr69U=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ=
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b h1:7gd+rd8P3bqcn/96gOZa3F5dpJr/vEiDQYlNb/y2uNs=
gitlab.com/nyarla/go-crypt v0.0.0-20160106005555-d9a5dc2b789b/go.mod h1:T3BPAOm2cqquPa0MKWeNkmOM5RQsRhkrwMWonFMN7fE=
golang.org/x/net v0.0.0-20220127200216-cd36cc0744dd/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=