- attach.UploadWriterOptions (was the unexported uploadWriterOptions) gives code that writes an upload to the bucket itself the same Content-Type and Content-Disposition: attachment for non-inline types that attach.Store stores - writeBlob calls it; Store behaviour unchanged - TestUploadWriterOptions table test - lagoon README, docs/database/attachments.md and docs/services/storage.md describe it for writers that bypass attach.Store
50 lines
1.9 KiB
Go
50 lines
1.9 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 returns the blob writer options of an upload: the
|
|
// content type, plus Content-Disposition: attachment (no filename parameter)
|
|
// for every type IsInlineContentType does not report as inline. Store writes
|
|
// with these options. Code that writes an upload to the bucket itself, with
|
|
// NewWriter or WriteAll, passes the sniffed type (the value stored in
|
|
// content_type) and names the file with DiskExtension, so its blob is served
|
|
// like one Store wrote. Each call returns a new value the caller may extend.
|
|
func UploadWriterOptions(contentType string) *blob.WriterOptions {
|
|
opts := &blob.WriterOptions{ContentType: contentType}
|
|
if !IsInlineContentType(contentType) {
|
|
opts.ContentDisposition = attachmentDisposition
|
|
}
|
|
return opts
|
|
}
|