mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
feat(s3): customize filenames via placeholders (#1285)
* feat(s3): customize filenames via placeholders * fix go-static-checks * add tips on the frontend * fix eslint check * remove yarn.lock * remove Config.Path * update tips * fix * update
This commit is contained in:
@ -4,7 +4,6 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"path"
|
|
||||||
|
|
||||||
"github.com/aws/aws-sdk-go-v2/aws"
|
"github.com/aws/aws-sdk-go-v2/aws"
|
||||||
s3config "github.com/aws/aws-sdk-go-v2/config"
|
s3config "github.com/aws/aws-sdk-go-v2/config"
|
||||||
@ -19,7 +18,6 @@ type Config struct {
|
|||||||
SecretKey string
|
SecretKey string
|
||||||
Bucket string
|
Bucket string
|
||||||
EndPoint string
|
EndPoint string
|
||||||
Path string
|
|
||||||
Region string
|
Region string
|
||||||
URLPrefix string
|
URLPrefix string
|
||||||
}
|
}
|
||||||
@ -57,7 +55,7 @@ func (client *Client) UploadFile(ctx context.Context, filename string, fileType
|
|||||||
uploader := manager.NewUploader(client.Client)
|
uploader := manager.NewUploader(client.Client)
|
||||||
uploadOutput, err := uploader.Upload(ctx, &awss3.PutObjectInput{
|
uploadOutput, err := uploader.Upload(ctx, &awss3.PutObjectInput{
|
||||||
Bucket: aws.String(client.Config.Bucket),
|
Bucket: aws.String(client.Config.Bucket),
|
||||||
Key: aws.String(path.Join(client.Config.Path, filename)),
|
Key: aws.String(filename),
|
||||||
Body: src,
|
Body: src,
|
||||||
ContentType: aws.String(fileType),
|
ContentType: aws.String(fileType),
|
||||||
ACL: types.ObjectCannedACL(*aws.String("public-read")),
|
ACL: types.ObjectCannedACL(*aws.String("public-read")),
|
||||||
|
@ -7,6 +7,7 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
|
"path"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@ -134,11 +135,27 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
|
|
||||||
if storage.Type == api.StorageS3 {
|
if storage.Type == api.StorageS3 {
|
||||||
s3Config := storage.Config.S3Config
|
s3Config := storage.Config.S3Config
|
||||||
|
t := time.Now()
|
||||||
|
s3FileKey := s3Config.Path
|
||||||
|
if s3Config.Path == "" {
|
||||||
|
s3FileKey = filename
|
||||||
|
} else if !strings.Contains(s3Config.Path, "{filename}") {
|
||||||
|
s3FileKey = path.Join(s3Config.Path, filename)
|
||||||
|
} else {
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{filename}", filename)
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{filetype}", filetype)
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{timestamp}", fmt.Sprintf("%d", t.Unix()))
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{year}", fmt.Sprintf("%d", t.Year()))
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{month}", fmt.Sprintf("%02d", t.Month()))
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{day}", fmt.Sprintf("%02d", t.Day()))
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{hour}", fmt.Sprintf("%02d", t.Hour()))
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{minute}", fmt.Sprintf("%02d", t.Minute()))
|
||||||
|
s3FileKey = strings.ReplaceAll(s3FileKey, "{second}", fmt.Sprintf("%02d", t.Second()))
|
||||||
|
}
|
||||||
s3client, err := s3.NewClient(ctx, &s3.Config{
|
s3client, err := s3.NewClient(ctx, &s3.Config{
|
||||||
AccessKey: s3Config.AccessKey,
|
AccessKey: s3Config.AccessKey,
|
||||||
SecretKey: s3Config.SecretKey,
|
SecretKey: s3Config.SecretKey,
|
||||||
EndPoint: s3Config.EndPoint,
|
EndPoint: s3Config.EndPoint,
|
||||||
Path: s3Config.Path,
|
|
||||||
Region: s3Config.Region,
|
Region: s3Config.Region,
|
||||||
Bucket: s3Config.Bucket,
|
Bucket: s3Config.Bucket,
|
||||||
URLPrefix: s3Config.URLPrefix,
|
URLPrefix: s3Config.URLPrefix,
|
||||||
@ -147,7 +164,7 @@ func (s *Server) registerResourceRoutes(g *echo.Group) {
|
|||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to new s3 client").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to new s3 client").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
link, err := s3client.UploadFile(ctx, filename, filetype, src)
|
link, err := s3client.UploadFile(ctx, s3FileKey, filetype, src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upload via s3 client").SetInternal(err)
|
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to upload via s3 client").SetInternal(err)
|
||||||
}
|
}
|
||||||
|
@ -185,6 +185,11 @@ const CreateStorageServiceDialog: React.FC<Props> = (props: Props) => {
|
|||||||
Path
|
Path
|
||||||
<span className="text-sm text-gray-400 ml-1">(Storage Path)</span>
|
<span className="text-sm text-gray-400 ml-1">(Storage Path)</span>
|
||||||
</Typography>
|
</Typography>
|
||||||
|
<Typography className="!mb-1" level="body2">
|
||||||
|
<p className="text-sm text-gray-400 ml-1">{"You can use {year}, {month}, {day}, {hour}, {minute}, {second},"}</p>
|
||||||
|
<p className="text-sm text-gray-400 ml-1">{"{filetype}, {filename}, {timestamp} and any other words."}</p>
|
||||||
|
<p className="text-sm text-gray-400 ml-1">{"e.g., {year}/{month}/{day}/your/path/{filename}.{filetype}"}</p>
|
||||||
|
</Typography>
|
||||||
<Input
|
<Input
|
||||||
className="mb-2"
|
className="mb-2"
|
||||||
placeholder="Path"
|
placeholder="Path"
|
||||||
|
Reference in New Issue
Block a user