diff --git a/pkg/files/files.go b/pkg/files/files.go index 8c67c6550..4c8460c8b 100644 --- a/pkg/files/files.go +++ b/pkg/files/files.go @@ -37,6 +37,7 @@ import ( "github.com/aws/aws-sdk-go-v2/aws" "github.com/aws/aws-sdk-go-v2/service/s3" "github.com/c2h5oh/datasize" + "github.com/gabriel-vasile/mimetype" "github.com/spf13/afero" "xorm.io/xorm" ) @@ -86,7 +87,14 @@ func (f *File) LoadFileMetaByID() (err error) { // Create creates a new file from an FileHeader func Create(f io.ReadSeeker, realname string, realsize uint64, a web.Auth) (file *File, err error) { - return CreateWithMime(f, realname, realsize, a, "") + mime, err := mimetype.DetectReader(f) + if err != nil { + return nil, fmt.Errorf("failed to detect mime type: %w", err) + } + if _, err := f.Seek(0, io.SeekStart); err != nil { + return nil, fmt.Errorf("failed to seek after mime detection: %w", err) + } + return CreateWithMime(f, realname, realsize, a, mime.String()) } // CreateWithMime creates a new file from an FileHeader and sets its mime type diff --git a/pkg/files/files_test.go b/pkg/files/files_test.go index 70377fd32..cdaad2f5d 100644 --- a/pkg/files/files_test.go +++ b/pkg/files/files_test.go @@ -18,6 +18,8 @@ package files import ( "bytes" + "image" + "image/png" "os" "testing" @@ -60,6 +62,37 @@ func TestCreate(t *testing.T) { }) } +func TestCreateDetectsMimeType(t *testing.T) { + initFixtures(t) + ta := &testauth{id: 1} + + // Minimal valid PNG (1x1 pixel) + pngData := createMinimalPNG(t) + + f, err := Create(bytes.NewReader(pngData), "test.png", uint64(len(pngData)), ta) + require.NoError(t, err) + assert.Equal(t, "image/png", f.Mime) +} + +func TestCreateDetectsMimeTypePlainText(t *testing.T) { + initFixtures(t) + ta := &testauth{id: 1} + + textData := []byte("hello world this is plain text") + + f, err := Create(bytes.NewReader(textData), "readme.txt", uint64(len(textData)), ta) + require.NoError(t, err) + assert.Equal(t, "text/plain; charset=utf-8", f.Mime) +} + +func createMinimalPNG(t *testing.T) []byte { + t.Helper() + img := image.NewRGBA(image.Rect(0, 0, 1, 1)) + buf := &bytes.Buffer{} + require.NoError(t, png.Encode(buf, img)) + return buf.Bytes() +} + func TestFile_Delete(t *testing.T) { t.Run("Normal", func(t *testing.T) { s := db.NewSession() diff --git a/pkg/models/task_attachment_test.go b/pkg/models/task_attachment_test.go index abdffd029..258c136d4 100644 --- a/pkg/models/task_attachment_test.go +++ b/pkg/models/task_attachment_test.go @@ -113,6 +113,7 @@ func TestTaskAttachment_NewAttachment(t *testing.T) { assert.Equal(t, testuser.ID, ta.File.CreatedByID) assert.Equal(t, "testfile", ta.File.Name) assert.Equal(t, uint64(100), ta.File.Size) + assert.NotEmpty(t, ta.File.Mime, "mime type should be detected and stored") // Extra test for max size test }