无法下载非图像媒体文件,上传至 S3 后原始文件名丢失

通过 rake uploads:migrate_to_s3 迁移到 S3 或存储在本地存储中的非图像媒体文件,在点击上传链接时会以原始文件名下载;而直接上传到 S3 的非图像媒体文件则会在新标签页中打开,且原始文件名会丢失。

rake uploads:migrate_to_s3 会为所有 非图像 上传设置 content_disposition

而直接上传到 S3 则仅会为所有 非媒体 上传设置 content_disposition

修复方法是将 is_supported_media 替换为 is_supported_image(已测试并确认按预期工作)。

3 个赞

我们需要这个修复吗 @sam

3 个赞

可能是 @martin,你觉得这个变更正确吗?

4 个赞

我_觉得_这个修复方案听起来是对的——让我在本地测试一下你提议的更改,如果看起来没问题,我会提交一个 PR。

3 个赞

再仔细看一下,我认为解决方案应该反过来——uploads:migrate_to_s3 任务的条件应该是 if !FileHelper.is_supported_media?(name)。给视频和音频文件添加 content-disposition: attachment; filename=X 头信息是不合理的。您是在 Discourse 帖子内流式传输这些文件,而不是下载它们吧?

因此,我们希望实现的效果是:

不添加 content-disposition attachment 头信息

  • 图片
  • 视频
  • 音频

添加 content-disposition attachment 头信息,并使用原始文件名

  • 所有其他附件/上传文件(PDF、TXT、CSV 等)

如果我遗漏了什么,请随时补充更多信息或示例。

3 个赞

相信我,我花了几天时间才弄清楚这一点,这对我来说也很奇怪。但是,将所有媒体文件(除图片外)的 content-disposition 设置为 attachment; filename=X,完美地 模拟 了当前从 本地存储 提供媒体文件的方式。

简而言之,不!如果需要,我可以使用 oneboxing 进行流式传输,但直接下载链接 [media_file](path_to_media_file)(其中路径可以是本地路径或 S3 路径)应该使用其 原始文件名 下载 文件,就像在本地存储上一样(对于 迁移 到 S3 的文件也是如此)。

但突然之间,直接上传到 S3 已无法实现这一点:[media_file](S3_path_to_media_file) 链接会在新标签页中流式传输媒体文件(这并不需要,因为这正是 oneboxing 所做的),而且当尝试从媒体播放器控件下载它时,它也会丢失原始文件名。

我期望本地托管的文件和 S3 托管的文件应该表现一致,对吧?按照你的提议,S3 托管上传的功能将完全反转,不仅适用于新上传的文件,也适用于已迁移的文件。

这里有一份详细的案例文件,说明为什么我认为我的提议是正确的(即它保留了本地托管和 S3 托管上传的相同功能):

本地托管的文件

我有一个大型(5000+)音频(语音)文件库,大小范围从 1MB 到 10MB,总计约 40GB。这些文件目前托管在本地存储上,现在正被转移到 S3(这是有意为之,我不希望它们托管在第三方服务上)。从性能角度来看,这已经运行得相当不错,但由于存储成本上升以及可以使用 S3 搭配 CDN 的选项,现在迁移到 S3 变得很有意义。

这些文件针对 大小 进行了优化,并非用于流式传输,而是用于下载并在本地收听(针对带宽/连接受限的客户端)。文件是批量上传的,然后在原始帖子中通过引用其各自的 SHA1 值生成的链接进行引用,格式为:[dl_link](https://discourse.forum.tld/uploads/default/original/3X/0/1/0123..sha1.mp3),并且可以通过点击文件的直接链接使用其 原始 文件名进行下载(参见示例 此处)。

另一方面,如果这些链接被 oneboxed,它们仍然可以直接从 Discourse 服务器流式传输(并且也可以从播放器控件下载,同样保留原始文件名)。

已迁移到 S3 的文件

当使用 uploads:migrate_to_s3 将上传文件从本地存储迁移到 S3 时,会发生以下两件事:

  • 除图片外的所有上传文件都会设置 content-disposition: attachment; filename=X
  • 原始帖子中的直接本地链接 [dl_link](https://discourse.forum.tld/uploads/default/original/3X/0/1/0123..sha1.mp3) 会被替换为 S3 链接 [dl_link](https://cdn_url/uploads/original/3X/0/1/0123..sha1.mp3)

这在各方面都模拟了本地托管的上传(包括带有原始文件名的下载链接以及 oneboxing)。

新上传到 S3 的文件

  • 对于所有媒体文件,设置 content-disposition: attachment; filename=X
  • 新上传的文件在原始内容中使用短 URL 引用,但生成的 HTML 链接仍直接指向 https://cdn_url/uploads/original/3X/0/1/0123..sha1.mp3
  • 点击短 URL 链接或手动插入的 S3 链接 [dl_link](https://cdn_url/uploads/original/3X/0/1/0123..sha1.mp3) 会在新标签页中打开文件,而不是下载它。

由于未设置 content-disposition,这现在与从本地存储提供媒体文件的方式不同(oneboxing 仍然有效,但带有原始文件名的下载链接不再可用)。

如果您需要任何额外信息,请告诉我。

2 个赞

太好了,感谢您提供所有这些额外的背景信息。我会尝试一下,并计划在下周提交一个拉取请求。

5 个赞

有没有可能将其纳入即将发布的最终 2.5 版本中?

1 个赞

说实话,由于其他紧迫的工作,我还没有进一步研究这个问题。我现在已经在日程中安排了一些时间,本周会认真查看此事。这个改动看起来很小,应该不会花太多时间。PR 完成后我会汇报。

4 个赞

@md-misko 我已确认您的用例,并在修复 content-disposition 后,我仍然可以正确流式传输音频和视频。修复正在构建中,预计今天结束前合并:

感谢您的耐心配合!

4 个赞

此主题已在 3 天后自动关闭。不再允许新的回复。