- attach.IsInlineContentType: the shared inline raster list (JPEG, PNG, GIF, WebP, AVIF), parameters and case ignored, false for empty or unparsable values - writeBlob stores Content-Disposition: attachment for every other type, so a public bucket or CDN makes the browser download HTML, SVG, PDF or plain text; content_type and thumbnails are unchanged - driver tests on memblob and fileblob, Postgres-backed Store assertion, lagoon README and the storage and attachments pages
45 lines
1.5 KiB
Go
45 lines
1.5 KiB
Go
package attach
|
|
|
|
import (
|
|
"mime"
|
|
"strings"
|
|
|
|
"gocloud.dev/blob"
|
|
)
|
|
|
|
// inlineContentTypes are the raster image types a browser may show inline
|
|
// from an upload.
|
|
var inlineContentTypes = map[string]bool{
|
|
"image/avif": true,
|
|
"image/gif": true,
|
|
"image/jpeg": true,
|
|
"image/png": true,
|
|
"image/webp": true,
|
|
}
|
|
|
|
// attachmentDisposition is the Content-Disposition stored with a non-inline
|
|
// upload. It is the bare value with no filename parameter: the client's file
|
|
// name never reaches blob metadata or a response header.
|
|
const attachmentDisposition = "attachment"
|
|
|
|
// IsInlineContentType reports whether contentType, with parameters and case
|
|
// ignored, is a raster image a browser may show inline from an upload (JPEG,
|
|
// PNG, GIF, WebP, AVIF). An empty or unparsable value is not. Store stores
|
|
// every other type, SVG, PDF, HTML and plain text included, with
|
|
// Content-Disposition: attachment, and the surf uploads route serves it as a
|
|
// download.
|
|
func IsInlineContentType(contentType string) bool {
|
|
mediaType, _, err := mime.ParseMediaType(contentType)
|
|
return err == nil && inlineContentTypes[strings.ToLower(mediaType)]
|
|
}
|
|
|
|
// uploadWriterOptions are the blob writer options of an upload: the content
|
|
// type, plus the attachment disposition when the type is not inline.
|
|
func uploadWriterOptions(contentType string) *blob.WriterOptions {
|
|
opts := &blob.WriterOptions{ContentType: contentType}
|
|
if !IsInlineContentType(contentType) {
|
|
opts.ContentDisposition = attachmentDisposition
|
|
}
|
|
return opts
|
|
}
|