diff --git a/server/media/fs/filesys.go b/server/media/fs/filesys.go index 8a56e01..fa26e11 100644 --- a/server/media/fs/filesys.go +++ b/server/media/fs/filesys.go @@ -9,7 +9,6 @@ import ( "errors" "hash/fnv" "io" - "mime" "net/http" "net/url" "os" @@ -141,10 +140,7 @@ func (fh *fshandler) Upload(fdef *types.FileDef, file io.Reader) (string, int64, } fname := fdef.Id - ext, _ := mime.ExtensionsByType(fdef.MimeType) - if len(ext) > 0 { - fname += ext[0] - } + fname += media.ExtensionByMimeType(fdef.MimeType) fdef.Location = location // Use file path to create ETag. File paths are unique so will be the ETag. diff --git a/server/media/media.go b/server/media/media.go index ab66baf..906e01a 100644 --- a/server/media/media.go +++ b/server/media/media.go @@ -4,6 +4,7 @@ package media import ( "errors" "io" + "mime" "net/http" "net/url" "path" @@ -68,6 +69,37 @@ type AllowedOrigin struct { var fileNamePattern = regexp.MustCompile(`^[-_A-Za-z0-9]+`) +// ExtensionByMimeType returns a stable URL extension for uploaded media. +func ExtensionByMimeType(mimeType string) string { + switch strings.ToLower(strings.TrimSpace(strings.Split(mimeType, ";")[0])) { + case "audio/x-m4a", "audio/m4a", "audio/mp4", "audio/mp4a-latm": + return ".m4a" + case "audio/aac", "audio/aacp": + return ".aac" + case "audio/mpeg", "audio/mp3": + return ".mp3" + case "audio/ogg": + return ".ogg" + case "audio/wav", "audio/x-wav", "audio/wave": + return ".wav" + case "audio/webm": + return ".webm" + case "image/pjpeg", "image/jpg": + return ".jpg" + case "image/jpeg": + return ".jpg" + case "image/jfif": + return ".jfif" + case "video/mp4": + return ".mp4" + } + exts, _ := mime.ExtensionsByType(mimeType) + if len(exts) > 0 { + return exts[0] + } + return "" +} + // GetIdFromUrl is a helper method for extracting file ID from a URL. func GetIdFromUrl(url, serveUrl string) types.Uid { dir, fname := path.Split(path.Clean(url)) diff --git a/server/media/media_test.go b/server/media/media_test.go index a5f85f4..8dafe02 100644 --- a/server/media/media_test.go +++ b/server/media/media_test.go @@ -219,3 +219,21 @@ func TestMatchCORSOrigin(t *testing.T) { func containsSubstring(str, substr string) bool { return strings.Contains(strings.ToLower(str), strings.ToLower(substr)) } + +func TestExtensionByMimeType(t *testing.T) { + cases := map[string]string{ + "audio/x-m4a": ".m4a", + "audio/x-m4a; charset=utf": ".m4a", + "audio/mp4": ".m4a", + "audio/aac": ".aac", + "audio/mpeg": ".mp3", + "image/jpeg": ".jpg", + "image/jfif": ".jfif", + "video/mp4": ".mp4", + } + for mimeType, want := range cases { + if got := ExtensionByMimeType(mimeType); got != want { + t.Fatalf("ExtensionByMimeType(%q)=%q, want %q", mimeType, got, want) + } + } +} diff --git a/server/media/oss/oss.go b/server/media/oss/oss.go index 4aaba39..d5b8629 100644 --- a/server/media/oss/oss.go +++ b/server/media/oss/oss.go @@ -7,7 +7,6 @@ import ( "errors" "hash/fnv" "io" - "mime" "net/http" "net/url" "path" @@ -247,10 +246,7 @@ func (oh *ossHandler) Upload(fdef *types.FileDef, file io.Reader) (string, int64 } fname := fdef.Id - ext, _ := mime.ExtensionsByType(fdef.MimeType) - if len(ext) > 0 { - fname += ext[0] - } + fname += media.ExtensionByMimeType(fdef.MimeType) fdef.Location = key fdef.ETag = etagFromLocation(key) diff --git a/server/media/s3/s3.go b/server/media/s3/s3.go index 2bc84b4..f75acf4 100644 --- a/server/media/s3/s3.go +++ b/server/media/s3/s3.go @@ -6,7 +6,6 @@ import ( "encoding/json" "errors" "io" - "mime" "net/http" "net/url" "path" @@ -280,22 +279,23 @@ func (ah *awshandler) Upload(fdef *types.FileDef, file io.Reader) (string, int64 } rc := readerCounter{reader: file} - result, err := tmClient.UploadObject(context.Background(), &transfermanager.UploadObjectInput{ + input := &transfermanager.UploadObjectInput{ CacheControl: aws.String(ah.conf.CacheControl), Bucket: aws.String(ah.conf.BucketName), Key: aws.String(key), Body: &rc, - }) + } + if fdef.MimeType != "" { + input.ContentType = aws.String(fdef.MimeType) + } + result, err := tmClient.UploadObject(context.Background(), input) if err != nil { return "", 0, err } fname := fdef.Id - ext, _ := mime.ExtensionsByType(fdef.MimeType) - if len(ext) > 0 { - fname += ext[0] - } + fname += media.ExtensionByMimeType(fdef.MimeType) fdef.Location = key if result.ETag != nil {