# 损坏的图片及其 S3 URL

**URL:** <https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889>\
**Category:** Support\
**Created:** [2020年六月25日 07:46 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889 "2020-06-25T07:46:00Z")\
**Posts on this page:** 14\
**Page:** 2

<div class="post-metadata">

**Author:** ![masterakay](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/masterakay/32/122593_2.png) [@masterakay](https://meta.discourse.org/u/masterakay)\
**Post date:** [2020年七月19日 04:55 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/23 "2020-07-19T04:55:21Z")

</div>

@schleifer 嘿，之后能给我们一些指导吗？

---

<div class="post-metadata">

**Author:** ![schleifer](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/schleifer/32/86416_2.png) [@schleifer](https://meta.discourse.org/u/schleifer)\
**Post date:** [2020年七月20日 03:17 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/24 "2020-07-20T03:17:12Z")

</div>

> [@rithvikvibhu](#):
>
> 新上传的文件（运行正常）存储在 `/original/2X/*/.jpg`

好的，这是我们可以处理的情况。首先，将 `/default/*` 中的所有文件移动到 `/original/1X/*`。

> [@rithvikvibhu](#):
>
> `/default/` 似乎已经包含所有图片了。

这对我们来说是已知的，但数据库还不知道。下一步将调整数据库中所有上传文件的路径。不过在更改其他内容之前，让我们先进行合理性检查。

启动数据库控制台：

```plaintext
cd /var/discourse
./launcher enter
rails db

```

运行以下查询以查看结果：

```plaintext
select id,url from uploads where id > 0 and url not like '//PREFIX/original/%'

```

你需要将 PREFIX 替换为 BUCKET + ‘.s3.dualstack.’ + REGION + ‘.amazonaws.com’，例如 `//pesioforum.s3.dualstack.us-west-2.amazonaws.com/original/%`。

这应该会输出 `(0 rows)`。如果不是，那么我们还需要额外的步骤。

---

<div class="post-metadata">

**Author:** ![rithvikvibhu](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rithvikvibhu/32/185155_2.png) [@rithvikvibhu](https://meta.discourse.org/u/rithvikvibhu)\
**Post date:** [2020年七月20日 07:48 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/25 "2020-07-20T07:48:44Z")

</div>

您的查询共有 7 个上传文件，且均非来自 S3。  
因此，所有 S3 链接都仅指向原始文件，对吗？这 7 个上传文件来自我们开始使用 S3 进行上传之前（2018 年 10 月）。

 ![image](https://global.discourse-cdn.com/meta/original/3X/7/4/7417b47e1f5d773ccebf42e729ad922bbdcc2495.png)

在 S3 链接（共 2614 个）中：  
2368 个使用 `//pesioforum.s3.dualstack.ap-south-1.amazonaws.com`  
246 个使用 `//pesioforum.s3.ap-south-1.amazonaws.com`

这两个链接均可正常工作，在此提及是因为它们可能会影响我们可能使用的任何正则表达式。

---

<div class="post-metadata">

**Author:** ![masterakay](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/masterakay/32/122593_2.png) [@masterakay](https://meta.discourse.org/u/masterakay)\
**Post date:** [2020年七月20日 12:30 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/26 "2020-07-20T12:30:35Z")

</div>

@schleifer 请帮我们完成这项工作。☺

---

<div class="post-metadata">

**Author:** ![riking](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/riking/32/170938_2.png) [@riking](https://meta.discourse.org/u/riking)\
**Post date:** [2020年七月20日 20:13 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/27 "2020-07-20T20:13:04Z")

</div>

好的，您可以将文件从 `/default/` 移动到 `/original/1X`。

---

<div class="post-metadata">

**Author:** ![schleifer](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/schleifer/32/86416_2.png) [@schleifer](https://meta.discourse.org/u/schleifer)\
**Post date:** [2020年七月21日 01:35 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/28 "2020-07-21T01:35:52Z")

</div>

> [@rithvikvibhu](#):
>
> 这 7 个上传文件来自我们开始使用 S3 进行上传之前（2018 年 10 月）。

你可以通过运行 [`rake s3:upload_assets`](https://github.com/discourse/discourse/blob/master/lib/tasks/s3.rake#L187) 将这些文件迁移到 S3。

> [@rithvikvibhu](#):
>
> 有 246 条记录使用了 `//pesioforum.s3.ap-south-1.amazonaws.com`。

双栈端点同时支持 IPv6 和 IPv4，而另一个端点仅支持 IPv4。

镜像中有一个用于在数据库中重映射字符串的脚本。在运行该脚本之前，请务必通过 `/admin/backups`（汉堡菜单 → 管理 → 备份）进行备份。

以下命令应可修复这 246 条记录：

```plaintext
discourse remap '//pesioforum.s3.ap-south-1.amazonaws.com/original/' '//pesioforum.s3.dualstack.ap-south-1.amazonaws.com/original/'

```

在将 `/default/` 下的所有内容移动到 `/original/1X/` 之后，我们可以在数据库中重映射这些文件。但在此之前，我们需要确保 `/original/2X` 下的所有内容确实存在。

以下查询返回的行数是否与存储桶中该路径下的实际对象数量一致？  
`select url from uploads where url like '//pesioforum.s3.dualstack.us-west-2.amazonaws.com/original/2X/%'`

---

<div class="post-metadata">

**Author:** ![rithvikvibhu](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rithvikvibhu/32/185155_2.png) [@rithvikvibhu](https://meta.discourse.org/u/rithvikvibhu)\
**Post date:** [2020年七月21日 15:48 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/29 "2020-07-21T15:48:57Z")

</div>

你好 @schleifer

> 你可以通过运行 [`rake s3:upload_assets `](https://github.com/discourse/discourse/blob/master/lib/tasks/s3.rake#L187) 将这些迁移到 S3。

我运行了该命令，它确实上传了网站的资源文件（js、css 等）。但仍有 **7 个文件未被上传** 。  
我发现了 `rake uploads:migrate_to_s3` 这个任务，想确认这是否是正确的任务。

> 镜像中有一个用于重映射数据库中字符串的脚本。

这个脚本运行良好，`uploads` 表中已不再包含任何旧的、非双栈的链接。

> 但在此之前，我们需要确保 `/original/2X` 目录下的所有内容都实际存在。

遗憾的是，情况并非如此。S3 存储桶中有 521 个文件，但 `uploads` 表中有 2186 条记录。  
我测试了几个不在 `/original/2X/` 中所需的文件，发现它们都位于 `/default/` 目录下。

示例：从 `uploads` 表中看，  
[https://pesioforum.s3.dualstack.ap-south-1.amazonaws.com/original/2X/8/806a660beb158e9f06d07ffcd2370b389bbd250b.jpeg](https://pesioforum.s3.dualstack.ap-south-1.amazonaws.com/original/2X/8/806a660beb158e9f06d07ffcd2370b389bbd250b.jpeg) 不存在，但该文件实际上位于  
[https://pesioforum.s3.dualstack.ap-south-1.amazonaws.com/default/806a660beb158e9f06d07ffcd2370b389bbd250b.jpeg](https://pesioforum.s3.dualstack.ap-south-1.amazonaws.com/default/806a660beb158e9f06d07ffcd2370b389bbd250b.jpeg)

目前，作为一次性的临时方案，我们接受将所有文件从 `/original/2X/{}/` 移动到 `/original/1X/`，并更新帖子等内容的链接。  
新上传的文件本来就会正确放入 `2X` 目录。

---

<div class="post-metadata">

**Author:** ![schleifer](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/schleifer/32/86416_2.png) [@schleifer](https://meta.discourse.org/u/schleifer)\
**Post date:** [2020年七月22日 13:21 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/30 "2020-07-22T13:21:33Z")

</div>

> [@rithvikvibhu](#):
>
> 我找到了 `rake uploads:migrate_to_s3`，但想确认这是否是正确的任务。

啊，是的，这正是我原本打算用的。它应该能推送最后七条上传。

> [@rithvikvibhu](#):
>
> 目前，作为一次性临时方案，我们接受直接将 `/original/2X/{}/` 下的所有文件移动到 `/original/1X/`，并更新帖子等内容的链接。  
> 新的上传本来就会被正确放置到 `2X` 目录中。

确实，这是目前最好的选择。将所有文件从它们的 `/2X/` 子前缀中复制出来，并全部移动到 `/1X/` 目录。

一切就绪后，运行以下命令以更新所有数据库条目：

```plaintext
discourse remap --regex "//pesioforum\.doublestack\.s3\.ap-south-1\.amazonaws\.com/original/[1234]X/([0-9a-f]/){0,}" "//pesioforum.doublestack.s3.ap-south-1.amazonaws.com/original/1X/"

```

（请记住之前关于备份的警告。）

之后，某些帖子可能需要通过扳手菜单重新生成 HTML 版本。如果数量较多，可以使用 `rake posts:rebake` 命令批量重建所有帖子。

---

<div class="post-metadata">

**Author:** ![rithvikvibhu](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rithvikvibhu/32/185155_2.png) [@rithvikvibhu](https://meta.discourse.org/u/rithvikvibhu)\
**Post date:** [2020年七月23日 18:58 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/31 "2020-07-23T18:58:43Z")

</div>

@schleifer 成功了！通过修改正则表达式并重新烘焙所有帖子，大部分图片和上传内容现在都能正常工作了。  
还有少数图片（非帖子内容）仍然链接到 `/optimized/`，但我们可以手动修复。例如：不同主题中的徽标等。

非常感谢你的帮助！

---

<div class="post-metadata">

**Author:** ![41821](https://avatars.discourse-cdn.com/v4/letter/4/c4cdca/32.png) [@41821](https://meta.discourse.org/u/41821)\
**Post date:** [2020年八月4日 08:04 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/32 "2020-08-04T08:04:38Z")

</div>

你好，我们在自己的环境中也遇到了与此类似的问题，希望能得到帮助以解决它。

我们的问题在很多方面与此相似：

1. 我们在 `s3 upload bucket` 和 `s3 backup bucket` 下列出了相同的值。
2. 我们在升级 Discourse 时遇到了此问题：

```plaintext
旧版本：v2.3.0.beta3
新版本：v2.5.0.beta6

```

1. 我进入 Discourse 容器并查询了数据库：

```plaintext
SELECT id,url FROM uploads where id > 0 and url not like '//acme-forum.s3.dualstack.us-west-2.amazonaws.com/original/%';

```

```plaintext
 id | url
----+----------------------------------------------------------------------------------------------------
  1 | /uploads/default/original/1X/eb17xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxc33.png
  2 | /uploads/default/original/1X/b87fxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxv21.png
 78 | //acme-forum.s3-us-west-2.amazonaws.com/original/1X/1205xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxv045.png
(3 rows)

```

1. 我进入 Discourse 容器并查询了数据库：

```plaintext
select url from uploads where url like '//acme-forum.s3.dualstack.us-west-2.amazonaws.com/original/3X/%';

```

```plaintext
 //acme-forum.s3.dualstack.us-west-2.amazonaws.com/original/3X/6/2/6267xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxf607c.jpeg
(7953 rows)

```

1. 我检查了 ./original/3X/ 中有多少项，答案是 `251` 项。

问题：

1. 我们使用的是 `dualstack`，我不希望将我们的 URL 重新映射为不使用它。
2. 我们的文件夹结构有所不同，我们有类似 `3X/X/Y` 的结构（例如：`3X/7/a`），那么如何将所有内容从 `default` 移动到 `3X/*`，这样仍然无法正确映射？

我目前的想法是编写一个脚本，引用步骤 4 的输出，以确定将文件移回 `./original/3X/X/Y` 文件夹的位置。

唯一的问题是，当我这样做时，`dualstack` 尚未托管该文件。我的意思是，当我将文件替换到 original/3X/X/Y 时，我可以在以下地址看到它：  
**已损坏** [https://acme-forum.s3.dualstack.us-west-2.amazonaws.com/original/3X/6/b/6b6xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa001.png](https://acme-forum.s3.dualstack.us-west-2.amazonaws.com/original/3X/6/b/6b6xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa001.png)

**正常** [https://acme-forum.s3-us-west-2.amazonaws.com/original/3X/6/b/6b6xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa001.png](https://acme-forum.s3-us-west-2.amazonaws.com/original/3X/6/b/6b6xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxa001.png)

**更新** 事实证明，dualstack 端点从未像我最初认为的那样损坏，我在最初将图像文件复制到 ./original/3X/6/b 时犯了一个错误，忘记允许所有人读取。

所以我的问题是：  
将图像文件从 `./default` 移回 `./original/3X/x/y` 而完全不修改数据库，这是否是一个可行的选项？

---

<div class="post-metadata">

**Author:** ![41821](https://avatars.discourse-cdn.com/v4/letter/4/c4cdca/32.png) [@41821](https://meta.discourse.org/u/41821)\
**Post date:** [2020年八月5日 04:50 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/33 "2020-08-05T04:50:14Z")

</div>

好的，我有一个更新。  
看起来我可以预测 `./original` 图片应该放置的位置，但我不确定如何修复 `./optimized/` 图片的问题。

在我们的论坛中，如果浏览到某篇帖子，它会尝试显示 `./optimized` 图片。

有没有办法判断哪些是 `optimized` 图片？

我的想法是，优化后的图片文件名以 `_2_10x10.png` 结尾，这个假设合理吗？如果是的话，是否可以用一个脚本来实现：将所有包含类似 `_2_10x10.png` 的文件复制到 `optimized` 文件夹，而将不包含此类后缀的文件直接复制到 `./original` 文件夹？

示例：

```plaintext
GET https://acme-forum.s3.dualstack.us-west-2.amazonaws.com/optimized/3X/c/c/ccaxxxxxxxxxxxxxxxxxxxxxxxxxxxx85_2_690x268.png
[HTTP/1.1 403 Forbidden 0ms]

```

谢谢！

---

<div class="post-metadata">

**Author:** ![rithvikvibhu](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rithvikvibhu/32/185155_2.png) [@rithvikvibhu](https://meta.discourse.org/u/rithvikvibhu)\
**Post date:** [2020年八月10日 08:04 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/34 "2020-08-10T08:04:20Z")

</div>

@41821 如果 `uploads` 表中的 URL **正确且可用** ，但帖子仍尝试加载优化后的图片，那么清空 `optimized_images` 表并重新烘焙所有帖子即可解决：`discourse=> delete from optimized_images;`

---

<div class="post-metadata">

**Author:** ![41821](https://avatars.discourse-cdn.com/v4/letter/4/c4cdca/32.png) [@41821](https://meta.discourse.org/u/41821)\
**Post date:** [2020年八月31日 08:17 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/35 "2020-08-31T08:17:55Z")

</div>

非常感谢你的反馈。实际上，我最终通过编写一个脚本来解决问题（如果可以这么说的话），该脚本根据文件名将图片从 /default 目录移回 /optimized 目录。这似乎奏效了，我现在没有任何问题了。

不过，如果未来再次发生这种情况，我会按照你的建议，清空 optimized\_images 中的所有文件并重新烘焙。

谢谢！

---

<div class="post-metadata">

**Author:** ![system](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/system/32/443519_2.png) [@system](https://meta.discourse.org/u/system)\
**Post date:** [2020年九月30日 08:22 UTC](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889/36 "2020-09-30T08:22:54Z")

</div>

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.

[上一頁](https://meta.discourse.org/t/broken-images-and-their-s3-urls/155889.md?page=1)
