fix(drivers/s3): sign content-type for direct uploads (#3152)

* fix(s3): sign content type for direct uploads

- Include the inferred MIME type in presigned PutObject requests
- Return the signed Content-Type header for frontend uploads

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

* fix(drivers/s3): use client content type for direct uploads

- Accept and validate the client-provided direct upload media type
- Pass the type to the S3 signer through a typed context key
- Default missing types to application/octet-stream

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>

---------

Co-authored-by: Codex <267193182+codex@users.noreply.github.com>
This commit is contained in:
Mingluan Mu
2026-10-10 11:44:49 +08:00
committed by GitHub
parent 4f70daad70
commit 6bb4c8800a
3 changed files with 25 additions and 7 deletions
+9 -2
View File
@@ -9,6 +9,7 @@ import (
"strings"
"time"
"github.com/OpenListTeam/OpenList/v4/internal/conf"
"github.com/OpenListTeam/OpenList/v4/internal/driver"
"github.com/OpenListTeam/OpenList/v4/internal/errs"
"github.com/OpenListTeam/OpenList/v4/internal/model"
@@ -229,9 +230,14 @@ func (d *S3) GetDirectUploadInfo(ctx context.Context, _ string, dstDir model.Obj
return nil, errs.NotImplement
}
path := getKey(stdpath.Join(dstDir.GetPath(), fileName), false)
contentType, _ := ctx.Value(conf.DirectUploadContentTypeKey).(string)
if contentType == "" {
contentType = "application/octet-stream"
}
req, _ := d.directUploadClient.PutObjectRequest(&s3.PutObjectInput{
Bucket: &d.Bucket,
Key: &path,
Bucket: &d.Bucket,
Key: &path,
ContentType: &contentType,
})
if req == nil {
return nil, fmt.Errorf("failed to create PutObject request")
@@ -243,6 +249,7 @@ func (d *S3) GetDirectUploadInfo(ctx context.Context, _ string, dstDir model.Obj
return &model.HttpDirectUploadInfo{
UploadURL: link,
Method: "PUT",
Headers: map[string]string{"Content-Type": contentType},
}, nil
}
+1
View File
@@ -197,4 +197,5 @@ const (
PathKey
SharingIDKey
SkipHookKey
DirectUploadContentTypeKey
)
+15 -5
View File
@@ -1,6 +1,8 @@
package handles
import (
"context"
"mime"
"net/url"
stdpath "path"
@@ -15,10 +17,11 @@ import (
)
type FsGetDirectUploadInfoReq struct {
Path string `json:"path" form:"path"`
FileName string `json:"file_name" form:"file_name"`
FileSize int64 `json:"file_size" form:"file_size"`
Tool string `json:"tool" form:"tool"`
Path string `json:"path" form:"path"`
FileName string `json:"file_name" form:"file_name"`
FileSize int64 `json:"file_size" form:"file_size"`
ContentType string `json:"content_type" form:"content_type"`
Tool string `json:"tool" form:"tool"`
}
// FsGetDirectUploadInfo returns the direct upload info if supported by the driver
@@ -91,7 +94,14 @@ func FsGetDirectUploadInfo(c *gin.Context) {
return
}
}
directUploadInfo, err := fs.GetDirectUploadInfo(c, req.Tool, path, req.FileName, req.FileSize, overwrite)
if req.ContentType != "" {
if _, _, err := mime.ParseMediaType(req.ContentType); err != nil {
common.ErrorResp(c, err, 400)
return
}
}
ctx := context.WithValue(c, conf.DirectUploadContentTypeKey, req.ContentType)
directUploadInfo, err := fs.GetDirectUploadInfo(ctx, req.Tool, path, req.FileName, req.FileSize, overwrite)
if err != nil {
if !overwrite && errs.IsObjectAlreadyExists(err) {
common.ErrorStrResp(c, "file exists", 403)