Browse Source
fix: Use mime.FormatMediaType for RFC 6266 compliant Content-Disposition (#7635 )
Updated Content-Disposition header generation to use mime.FormatMediaType
from the standard library, which properly handles non-ASCII characters
and special characters per RFC 6266.
Changes:
- weed/server/common.go: Updated adjustHeaderContentDisposition to use
mime.FormatMediaType instead of manual escaping with fileNameEscaper
- weed/operation/upload_content.go: Updated multipart form Content-Disposition
to use mime.FormatMediaType
- weed/server/volume_server_handlers_read.go: Removed unused fileNameEscaper
This ensures correct filename display for international users across
filer downloads and file uploads.
Fixes #7634
pull/7636/head
Chris Lu
5 days ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with
12 additions and
13 deletions
weed/operation/upload_content.go
weed/server/common.go
weed/server/volume_server_handlers_read.go
@ -90,10 +90,9 @@ func (uploadResult *UploadResult) ToPbFileChunkWithSSE(fileId string, offset int
}
var (
fileNameEscaper = strings . NewReplacer ( ` \ ` , ` \\ ` , ` " ` , ` \" ` , "\n" , "" )
uploader * Uploader
uploaderErr error
once sync . Once
uploader * Uploader
uploaderErr error
once sync . Once
)
// HTTPClient interface for testing
@ -336,8 +335,9 @@ func (uploader *Uploader) upload_content(ctx context.Context, fillBufferFunction
body_writer = multipart . NewWriter ( option . BytesBuffer )
}
h := make ( textproto . MIMEHeader )
filename := fileNameEscaper . Replace ( option . Filename )
h . Set ( "Content-Disposition" , fmt . Sprintf ( ` form-data; name="file"; filename="%s" ` , filename ) )
// Use mime.FormatMediaType for RFC 6266 compliant Content-Disposition,
// properly handling non-ASCII characters and special characters
h . Set ( "Content-Disposition" , mime . FormatMediaType ( "form-data" , map [ string ] string { "name" : "file" , "filename" : option . Filename } ) )
h . Set ( "Idempotency-Key" , option . UploadUrl )
if option . MimeType == "" {
option . MimeType = mime . TypeByExtension ( strings . ToLower ( filepath . Ext ( option . Filename ) ) )
@ -9,9 +9,9 @@ import (
"fmt"
"io"
"io/fs"
"mime"
"mime/multipart"
"net/http"
"net/url"
"path/filepath"
"strconv"
"strings"
@ -286,14 +286,15 @@ func adjustHeaderContentDisposition(w http.ResponseWriter, r *http.Request, file
return
}
if filename != "" {
filename = url . QueryEscape ( filename )
contentDisposition := "inline"
dispositionType := "inline"
if r . FormValue ( "dl" ) != "" {
if dl , _ := strconv . ParseBool ( r . FormValue ( "dl" ) ) ; dl {
contentDisposition = "attachment"
dispositionType = "attachment"
}
}
w . Header ( ) . Set ( "Content-Disposition" , contentDisposition + ` ; filename=" ` + fileNameEscaper . Replace ( filename ) + ` " ` )
// Use mime.FormatMediaType for RFC 6266 compliant Content-Disposition,
// properly handling non-ASCII characters and special characters
w . Header ( ) . Set ( "Content-Disposition" , mime . FormatMediaType ( dispositionType , map [ string ] string { "filename" : filename } ) )
}
}
@ -34,8 +34,6 @@ import (
const reqIsProxied = "proxied"
var fileNameEscaper = strings . NewReplacer ( ` \ ` , ` \\ ` , ` " ` , ` \" ` )
func NotFound ( w http . ResponseWriter ) {
stats . VolumeServerHandlerCounter . WithLabelValues ( stats . ErrorGetNotFound ) . Inc ( )
w . WriteHeader ( http . StatusNotFound )