diff options
author | Alex Auvolat <alex@adnab.me> | 2021-08-16 15:30:14 +0200 |
---|---|---|
committer | Alex Auvolat <alex@adnab.me> | 2021-08-16 15:30:14 +0200 |
commit | e94bd728ec7f709883fb232b2eb123543ba5660e (patch) | |
tree | c7f75a9055e370df38dbba0c0f5b0c75a9dd649d /picture.go | |
parent | 9e3279b9c04bb07d108fa820a72841b4082c0979 (diff) | |
download | guichet-e94bd728ec7f709883fb232b2eb123543ba5660e.tar.gz guichet-e94bd728ec7f709883fb232b2eb123543ba5660e.zip |
Improve profile editing page & photo uploadingAdd_Directory
Diffstat (limited to 'picture.go')
-rw-r--r-- | picture.go | 184 |
1 files changed, 184 insertions, 0 deletions
diff --git a/picture.go b/picture.go new file mode 100644 index 0000000..d3590c8 --- /dev/null +++ b/picture.go @@ -0,0 +1,184 @@ +package main + +import ( + "bytes" + "context" + "errors" + "fmt" + "io" + "strconv" + + "image" + "image/jpeg" + _ "image/png" + + "mime/multipart" + "net/http" + "strings" + + "github.com/google/uuid" + "github.com/gorilla/mux" + "github.com/minio/minio-go/v7" + "github.com/minio/minio-go/v7/pkg/credentials" + "github.com/nfnt/resize" +) + +func newMinioClient() (*minio.Client, error) { + endpoint := config.S3Endpoint + accessKeyID := config.S3AccessKey + secretKeyID := config.S3SecretKey + useSSL := true + + //Initialize Minio + minioCLient, err := minio.New(endpoint, &minio.Options{ + Creds: credentials.NewStaticV4(accessKeyID, secretKeyID, ""), + Secure: useSSL, + Region: config.S3Region, + }) + + if err != nil { + return nil, err + } + + return minioCLient, nil +} + +//Upload image through guichet server. +func uploadProfilePicture(w http.ResponseWriter, r *http.Request, login *LoginStatus) (string, error) { + file, _, err := r.FormFile("image") + + if err == http.ErrMissingFile { + return "", nil + } + if err != nil { + return "", err + } + defer file.Close() + + err = checkImage(file) + if err != nil { + return "", err + } + + buffFull := bytes.NewBuffer([]byte{}) + buffThumb := bytes.NewBuffer([]byte{}) + err = resizePicture(file, buffFull, buffThumb) + if err != nil { + return "", err + } + + mc, err := newMinioClient() + if err != nil || mc == nil { + return "", err + } + + // If a previous profile picture existed, delete it + // (don't care about errors) + if nameConsul := login.UserEntry.GetAttributeValue(FIELD_NAME_PROFILE_PICTURE); nameConsul != "" { + mc.RemoveObject(context.Background(), config.S3Bucket, nameConsul, minio.RemoveObjectOptions{}) + mc.RemoveObject(context.Background(), config.S3Bucket, nameConsul+"-thumb", minio.RemoveObjectOptions{}) + } + + // Generate new random name for picture + nameFull := uuid.New().String() + nameThumb := nameFull + "-thumb" + + _, err = mc.PutObject(context.Background(), config.S3Bucket, nameThumb, buffThumb, int64(buffThumb.Len()), minio.PutObjectOptions{ + ContentType: "image/jpeg", + }) + if err != nil { + return "", err + } + + _, err = mc.PutObject(context.Background(), config.S3Bucket, nameFull, buffFull, int64(buffFull.Len()), minio.PutObjectOptions{ + ContentType: "image/jpeg", + }) + if err != nil { + return "", err + } + + return nameFull, nil +} + +func checkImage(file multipart.File) error { + buff := make([]byte, 512) //Detect read only the first 512 bytes + _, err := file.Read(buff) + if err != nil { + return err + } + file.Seek(0, 0) + + fileType := http.DetectContentType(buff) + fileType = strings.Split(fileType, "/")[0] + if fileType != "image" { + return errors.New("bad type") + } + + return nil +} + +func resizePicture(file multipart.File, buffFull, buffThumb *bytes.Buffer) error { + file.Seek(0, 0) + picture, _, err := image.Decode(file) + if err != nil { + return err + } + + thumbnail := resize.Thumbnail(90, 90, picture, resize.Lanczos3) + picture = resize.Thumbnail(480, 480, picture, resize.Lanczos3) + + err = jpeg.Encode(buffFull, picture, &jpeg.Options{ + Quality: 95, + }) + if err != nil { + return err + } + + err = jpeg.Encode(buffThumb, thumbnail, &jpeg.Options{ + Quality: 100, + }) + + return err +} + +func handleDownloadPicture(w http.ResponseWriter, r *http.Request) { + name := mux.Vars(r)["name"] + + //Check login + login := checkLogin(w, r) + if login == nil { + return + } + + //Get the object after connect MC + mc, err := newMinioClient() + if err != nil { + http.Error(w, "MinioClient: "+err.Error(), http.StatusInternalServerError) + return + } + + obj, err := mc.GetObject(context.Background(), "bottin-pictures", name, minio.GetObjectOptions{}) + if err != nil { + http.Error(w, "MinioClient: GetObject: "+err.Error(), http.StatusInternalServerError) + return + } + defer obj.Close() + + objStat, err := obj.Stat() + if err != nil { + http.Error(w, "MiniObjet: "+err.Error(), http.StatusInternalServerError) + return + } + + //Send JSON through xhttp + w.Header().Set("Content-Type", objStat.ContentType) + w.Header().Set("Content-Length", strconv.Itoa(int(objStat.Size))) + //Copy obj in w + writting, err := io.Copy(w, obj) + + if writting != objStat.Size || err != nil { + http.Error(w, fmt.Sprintf("WriteBody: %s, bytes wrote %d on %d", err.Error(), writting, objStat.Size), http.StatusInternalServerError) + return + } + +} |