fix(storage): COS 资源下载 - 公开 CDN 模式使用附件响应头 (#718)
This commit is contained in:
@@ -248,6 +248,28 @@ func SignedOriginObjectDownloadURL(setting Settings, objectKey string, expiresAt
|
||||
return signedOriginObjectURL(setting, objectKey, objectURLSigning{ExpiresAt: expiresAt, ContentDisposition: disposition})
|
||||
}
|
||||
|
||||
// PublicCDNObjectDownloadURL returns a public CDN URL that asks the object
|
||||
// storage origin to emit an attachment response. The query parameter keeps
|
||||
// ordinary display URLs inline while allowing a browser to download this one
|
||||
// without routing object bytes through the application server.
|
||||
//
|
||||
// Public CDN deployments must preserve response-content-disposition when
|
||||
// forwarding requests to the object store.
|
||||
func PublicCDNObjectDownloadURL(setting Settings, objectKey string, fileName string) (string, error) {
|
||||
value, err := OssCDNObjectURL(setting.CDNBaseURL, objectKey)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
parsed, err := url.Parse(value)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
query := parsed.Query()
|
||||
query.Set("response-content-disposition", objectDownloadContentDisposition(fileName, objectKey))
|
||||
parsed.RawQuery = query.Encode()
|
||||
return parsed.String(), nil
|
||||
}
|
||||
|
||||
func objectDownloadContentDisposition(fileName string, objectKey string) string {
|
||||
name := strings.TrimSpace(fileName)
|
||||
name = strings.ReplaceAll(name, "\\", "_")
|
||||
|
||||
@@ -76,6 +76,28 @@ func TestOneShotURLsKeepCurrentTimeSigningWithoutCacheOverride(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPublicCDNObjectDownloadURLForcesAttachmentOnlyOnDownloadURL(t *testing.T) {
|
||||
setting := Settings{CDNBaseURL: "https://media.example.com"}
|
||||
value, err := PublicCDNObjectDownloadURL(setting, "users/u-1/image/test image.png", "下载图片.png")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
parsed, err := url.Parse(value)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if parsed.Host != "media.example.com" || parsed.Path != "/users/u-1/image/test image.png" || !strings.HasPrefix(parsed.Query().Get("response-content-disposition"), "attachment") {
|
||||
t.Fatalf("download URL = %q", value)
|
||||
}
|
||||
inline, err := OssCDNObjectURL(setting.CDNBaseURL, "users/u-1/image/test image.png")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if parsedInline, err := url.Parse(inline); err != nil || parsedInline.RawQuery != "" {
|
||||
t.Fatalf("inline CDN URL = %q, %v", inline, err)
|
||||
}
|
||||
}
|
||||
|
||||
func mustParseQuery(t *testing.T, raw string) url.Values {
|
||||
t.Helper()
|
||||
parsed, err := url.Parse(raw)
|
||||
|
||||
Reference in New Issue
Block a user