12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576 |
- package httpheaders
- import (
- "fmt"
- "mime"
- "path/filepath"
- "strings"
- )
- const (
- // fallbackStem is used when the stem cannot be determined from the URL.
- fallbackStem = "image"
- // Content-Disposition header format
- contentDispositionsHeader = "%s; filename=\"%s%s\""
- // "inline" disposition types
- inlineDisposition = "inline"
- // "attachment" disposition type
- attachmentDisposition = "attachment"
- )
- // ContentDispositionValue generates the content-disposition header value.
- //
- // It uses the following priorities:
- // 1. By default, it uses the filename and extension from the URL.
- // 2. If `filename` is provided, it overrides the URL filename.
- // 3. If `contentType` is provided, it tries to determine the extension from the content type.
- // 4. If `ext` is provided, it overrides any extension determined from the URL or header.
- // 5. If the filename is still empty, it uses fallback stem.
- func ContentDispositionValue(url, filename, ext, contentType string, returnAttachment bool) string {
- // By default, let's use the URL filename and extension
- _, urlFilename := filepath.Split(url)
- urlExt := filepath.Ext(urlFilename)
- var rStem string
- // Avoid strings.TrimSuffix allocation by using slice operation
- if urlExt != "" {
- rStem = urlFilename[:len(urlFilename)-len(urlExt)]
- } else {
- rStem = urlFilename
- }
- var rExt = urlExt
- // If filename is provided explicitly, use it
- if len(filename) > 0 {
- rStem = filename
- }
- // If ext is provided explicitly, use it
- if len(ext) > 0 {
- rExt = ext
- } else if len(contentType) > 0 && rExt == "" {
- exts, err := mime.ExtensionsByType(contentType)
- if err == nil && len(exts) != 0 {
- rExt = exts[0]
- }
- }
- // If fallback is requested, and filename is still empty, override it with fallbackStem
- if len(rStem) == 0 {
- rStem = fallbackStem
- }
- disposition := inlineDisposition
- // Create the content-disposition header value
- if returnAttachment {
- disposition = attachmentDisposition
- }
- return fmt.Sprintf(contentDispositionsHeader, disposition, strings.ReplaceAll(rStem, `"`, "%22"), rExt)
- }
|