fix: detect and store mime type when creating file attachments

Use mimetype.DetectReader in files.Create to automatically detect and
store the MIME type from file content. This fixes task attachment
previews, S3 Content-Type headers, and UI display for newly uploaded
files.
This commit is contained in:
kolaente
2026-02-21 23:19:15 +01:00
parent 4babc477ef
commit 519f66a51f
3 changed files with 43 additions and 1 deletions

View File

@@ -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

View File

@@ -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()

View File

@@ -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
}