agecem-org/media/media.go
Victor Lacasse-Beaudoin 24855a4115 wip: ajouter MediaClient.UploadFormFiles
Une fois terminé, permettra de téléverser plusieurs documents à la fois
dans un même bucket.

Pour l'instant, est capable de recevoir des `[]*multipart.FileHeader` et
de valider leur `Content-Type` selon une liste prédéfinie (pdf, markdown
et plain text). Valide aussi que les pointeurs mémoires sont non-nil.

Retourne `http.StatusCreated` ainsi que la liste des documents validés qui
doivent être insérés.

Le travail restant est écrit en commentaires TODO
2023-12-18 17:40:37 -05:00

136 lines
3.6 KiB
Go

package media
import (
"context"
"errors"
"fmt"
"mime"
"mime/multipart"
"net/http"
"git.agecem.com/agecem/agecem-org/config"
"github.com/minio/minio-go/v7"
"github.com/minio/minio-go/v7/pkg/credentials"
"github.com/spf13/viper"
)
func NewMediaClient(endpoint, accessKeyId, secretAccessKey string, useSSL bool) (*MediaClient, error) {
if accessKeyId == "" {
return nil, errors.New("accessKeyId was found empty, but cannot be")
}
if secretAccessKey == "" {
return nil, errors.New("secretAccessKey was found empty, but cannot be")
}
var mediaClient MediaClient
minioClient, err := minio.New(endpoint, &minio.Options{
Creds: credentials.NewStaticV4(accessKeyId, secretAccessKey, ""),
Secure: useSSL,
})
if err != nil {
return &mediaClient, err
}
mediaClient.MinioClient = *minioClient
return &mediaClient, nil
}
func NewMediaClientFromViper() (*MediaClient, error) {
var cfg config.Config
if err := viper.Unmarshal(&cfg); err != nil {
return nil, err
}
mediaClient, err := NewMediaClient(cfg.Server.Documents.Endpoint, cfg.Server.Documents.AccessKeyId, cfg.Server.Documents.SecretAccessKey, cfg.Server.Documents.UseSSL)
if err != nil {
return mediaClient, err
}
return mediaClient, nil
}
type MediaClient struct {
MinioClient minio.Client
}
func (m *MediaClient) Seed() ([]string, error) {
var cfg config.Config
if err := viper.Unmarshal(&cfg); err != nil {
return nil, err
}
var new_buckets []string
for bucket := range cfg.Server.Documents.Buckets {
exists, err := m.MinioClient.BucketExists(context.Background(), bucket)
if err != nil {
return new_buckets, err
}
if exists {
continue
}
if err = m.MinioClient.MakeBucket(context.Background(), bucket, minio.MakeBucketOptions{}); err != nil {
return new_buckets, err
}
new_buckets = append(new_buckets, bucket)
}
return new_buckets, nil
}
func (m *MediaClient) UploadFormFiles(fileHeaders []*multipart.FileHeader) (statusCode int, result string) {
switch count := len(fileHeaders); count {
case 0:
return http.StatusBadRequest, "Veuillez sélectionner au moins 1 document à téléverser"
case 1:
result = "Téléversement de 1 fichier\n"
default:
result = fmt.Sprintf("Téléversement de %d fichiers\n", count)
}
var allowedMediaTypes = []string{"application/pdf", "text/markdown", "text/plain"}
var fileNames []string
for _, fileHeader := range fileHeaders {
fileNames = append(fileNames, fileHeader.Filename)
}
for i, fileHeader := range fileHeaders {
// Check for conflicting file names in upload
for j, fileName := range fileNames {
if fileName == fileHeader.Filename && i != j {
return http.StatusBadRequest, fmt.Sprintf("Doublon de nom de fichier '%s' trouvé, les noms de fichiers doivent être uniques", fileName)
}
}
//TODO check for conflicting fileNames with existing files
// Check media type
mediaType, _, err := mime.ParseMediaType(fileHeader.Header.Get("Content-Type"))
if err != nil {
return http.StatusBadRequest, fmt.Sprintf("Impossible de déterminer le type de fichier pour %d '%s'.\nPlus de détails: %s", i, fileHeader.Filename, err.Error())
}
var isAllowedMediaType bool
for _, allowedMediaType := range allowedMediaTypes {
if allowedMediaType == mediaType {
isAllowedMediaType = true
}
}
if !isAllowedMediaType {
return http.StatusBadRequest, fmt.Sprintf("Type de fichier interdit '%s' pour '%s'.\nTypes de fichiers permis: %s", mediaType, fileHeader.Filename, allowedMediaTypes)
}
result = fmt.Sprintf("%sDocument %d '%s' est de type '%s'\n",
result, i, fileHeader.Filename, mediaType)
//TODO Upload file
}
return http.StatusCreated, result
}