240 lines
4.8 KiB
Go
240 lines
4.8 KiB
Go
|
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
|
||
|
}
|