非图片上传未使用 S3 CDN URL

可能与此相关:上传到帖子时 S3 CDN 网址被忽略

起初我以为是自己漏掉了某些配置,但在此处的 meta 上可以复现:
https://meta.discourse.org/uploads/short-url/dw1U4hctATusBlHsUmWQXeme66j.csv此处上传)会重定向到
//assets-meta-cdck-prod-meta.s3.dualstack.us-west-1.amazonaws.com/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv

它难道不应该重定向到 https://d11a6trkgmumsb.cloudfront.net/original/3X/5/e/5ebb2cfb8cc907e8e8f7c6559a72d2f4a8ba2f8f.csv 吗?

5 个赞

嗯,这里可能有个问题 @martin,你能调查一下吗?如果可能的话,我们最好重定向到 CDN。

5 个赞

这有点棘手,我刚才看了一下。基本上,当我们进行“强制下载”时(即点击附件链接或图片上的“下载”按钮时),我们总是通过预签名 URL 从 S3 下载。这样做是为了添加适当的 content-disposition 头:

attachment; filename="#{upload.original_filename}"; filename*=UTF-8''#{upload.original_filename}

我认为 CDN URL 无法以这种方式工作?图片的 CDN URL 仅用于内联显示,而不用于下载。此外,对于具有私有 ACL 的安全图片和附件,必须始终使用预签名 URL。

2 个赞

@martin 关于附件链接,我无法看到它们如何设置为始终“强制下载”。目前,在上传非图像文件时,生成的渲染 URL 是一个没有 ?dl=1 参数的短 URL,它被解析为相应上传的 url 属性的值(它不是预签名 URL,并且在我们的情况下也会失败,因为 URL 不是 S3 cdn_url,而是可能仅适用于某些 S3 提供商的构造 URL)。

是否有办法始终强制下载附件,或者当前行为实际上是一个错误?

1 个赞

你能详细说明一下吗?你使用的是 Amazon S3 还是其他提供商?如果是,是哪一个?

1 个赞

是的,我似乎在使用一个_不支持_的 S3 提供商(OVH 对象存储

端点 URL 为 https://s3.de.ovh.cloud.net,配置的 s3 cdn_url 为 https://storage.de.ovh.cloud.net/v1/<some-unique-user-id>/<the-bucket-name>

当解析短 URL 时,Discourse 使用端点 URL 来构建生成的 URL(这会失败,因为它不包含正确的 OVH 用户 ID - s3 cdn_url 中的一部分)。

然而,强制短 URL 具有 dl=1 会构建一个有效的预签名 URL,这对我来说就足够了。

我在容器 YAML 中设置了这些(s3 特定的)环境变量:

DISCOURSE_USE_S3: true
DISCOURSE_S3_REGION: DE
DISCOURSE_S3_ENDPOINT: https://s3.de.cloud.ovh.net
DISCOURSE_S3_ACCESS_KEY_ID: ...
DISCOURSE_S3_SECRET_ACCESS_KEY: ...
DISCOURSE_S3_CDN_URL: https://storage.de.ovh.cloud.net/v1/<some-unique-user-id>/<the-bucket-name>
DISCOURSE_S3_UPLOAD_BUCKET: <the-bucket-name>
DISCOURSE_S3_INSTALL_CORS_RULE: false
1 个赞

也许这超出了本主题的范围,但如果当前行为是故意的,那么如何在前端覆盖短 URL 渲染?我想直接挂钩到帖子的烘焙过程,然后将查询参数附加到附件短 URL。我知道如何为 Discourse 编写 JS 插件,但大多数时候我只是很难找到正确的 Widget 来“重新打开”或覆盖函数。

好的,我找到了生成 Markdown 附件 的地方,据我所知,插件 API 无法(轻松地)覆盖它(我甚至认为不应该这样做)。

所以,我最初想在这些 URL 中添加 ?dl=1 参数的想法似乎是错误的方法。

关于不强制下载已解析的短 URL:如果我正确理解了 S3 存储桶公共 ACL 的反对意见,那么应该:

  1. 通过 CDN 提供 S3 文件(正如 @martin 指出的,对于附件来说是不可行的,因为在这种情况下我们可能无法正确设置下载文件名)
  2. 为 S3 对象创建预签名 URL

但目前的行为既没有这样做,也没有期望 S3 存储桶具有公共 ACL。对于支持的 S3 提供商(包括亚马逊)似乎也是如此,那么为什么在解析 S3 存储的短 URL 时,不将 Discourse.store.url_for 中的 force_download 选项默认设置为 true 呢?

1 个赞

我在这里遇到同样的问题,我期望的是 uploads/short-url 后面的文件能通过 S3 CDN URL 下载或重定向。

2 个赞

我们遇到了与Cloudflare R2相同的问题,因为它似乎不允许在没有预签名URL的情况下使用直接S3 URL。
而且R2不支持存储桶的ACL。

看起来 discourse 最近添加了一个“s3 use cdn url for all uploads”(对所有上传使用 CDN URL),这解决了这个问题。