fix(needle): use discovered file content type (#9851)

Problem: Multipart uploads where the first part was a form field and a later part contained the file used the first part's Content-Type for the file metadata.

Root cause: After finding a later part with a filename, parseUpload copied data and MD5 from part2 but read Content-Type from the original part variable.

Fix: Read Content-Type from the discovered file part.

Reproduction: go test ./weed/storage/needle -run TestParseUploadUsesDiscoveredFilePartContentType -count=1 failed before the fix because the parsed MIME type was text/plain instead of application/x-seaweed-test.

Validation: go test ./weed/storage/needle -run TestParseUploadUsesDiscoveredFilePartContentType -count=1; go test ./weed/storage/needle -count=1; git diff --check; git diff --cached --check
This commit is contained in:
7y-9
2026-06-08 02:50:34 +08:00
committed by GitHub
parent 058569c77b
commit 99bb5db1e3
2 changed files with 45 additions and 1 deletions
+1 -1
View File
@@ -208,7 +208,7 @@ func parseUpload(r *http.Request, sizeLimit int64, pu *ParsedUpload) (e error) {
// update
pu.Data = pu.bytesBuffer.Bytes()
pu.FileName = util.CleanWindowsPathBase(fName)
contentType = part.Header.Get("Content-Type")
contentType = part2.Header.Get("Content-Type")
pu.ContentMd5 = part2.Header.Get("Content-MD5")
part = part2
break
@@ -76,6 +76,50 @@ func TestParseUpload_GzipStreamCount(t *testing.T) {
}
}
func TestParseUploadUsesDiscoveredFilePartContentType(t *testing.T) {
var body bytes.Buffer
mw := multipart.NewWriter(&body)
fieldHeader := make(textproto.MIMEHeader)
fieldHeader.Set("Content-Disposition", `form-data; name="description"`)
fieldHeader.Set("Content-Type", "text/plain")
field, err := mw.CreatePart(fieldHeader)
if err != nil {
t.Fatalf("create field part: %v", err)
}
if _, err := field.Write([]byte("metadata")); err != nil {
t.Fatalf("write field part: %v", err)
}
fileHeader := make(textproto.MIMEHeader)
fileHeader.Set("Content-Disposition", `form-data; name="file"; filename="file.dat"`)
fileHeader.Set("Content-Type", "application/x-seaweed-test")
filePart, err := mw.CreatePart(fileHeader)
if err != nil {
t.Fatalf("create file part: %v", err)
}
if _, err := filePart.Write([]byte("payload")); err != nil {
t.Fatalf("write file part: %v", err)
}
if err := mw.Close(); err != nil {
t.Fatalf("close multipart writer: %v", err)
}
req := httptest.NewRequest(http.MethodPost, "/upload", bytes.NewReader(body.Bytes()))
req.Header.Set("Content-Type", mw.FormDataContentType())
pu, err := ParseUpload(req, 1024, &bytes.Buffer{})
if err != nil {
t.Fatalf("ParseUpload: %v", err)
}
if pu.FileName != "file.dat" {
t.Fatalf("FileName = %q, want file.dat", pu.FileName)
}
if pu.MimeType != "application/x-seaweed-test" {
t.Fatalf("MimeType = %q, want application/x-seaweed-test", pu.MimeType)
}
}
func gzipBytes(t *testing.T, in []byte) []byte {
t.Helper()
var buf bytes.Buffer