# 画像を孤立させて削除させるには？

**URL:** https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231
**Category:** Support
**Created:** [2018 年 1 月 29 日午前 12:52 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231 "2018-01-29T00:52:45Z")
**Posts on this page:** 20
**Page:** 1

<div class="post-metadata">

### Author: ![meglio](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/meglio/32/71444_2.png) [@meglio](https://meta.discourse.org/u/meglio)
#### Post date: [2018 年 1 月 29 日午前 12:52 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/1 "2018-01-29T00:52:45Z")

</div>

Because message revisions are kept, and older removed messages are also kept, and even removed topics are still there in database, how do I make an image orphaned so it gets removed automatically by a sidekiq job?

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2018 年 1 月 29 日午前 2:07 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/2 "2018-01-29T02:07:56Z")

</div>

I believe this is already how it works, the files are already removed unless the file is referenced in the current post revision. @zogstrip can clarify.

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [2018 年 1 月 29 日午前 8:18 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/3 "2018-01-29T08:18:14Z")

</div>

All the details are available in this job

> <https://github.com/discourse/discourse/blob/main/app/jobs/scheduled/clean_up_uploads.rb>

TL;DR: an image is orphaned if and only if it’s not referenced

- in the latest version of a post
- in a draft
- in a queued post
- in a logo site setting
- in a custom emoji
- in a theme
- in a user avatar/background/card image
- in a category logo/background image

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2019 年 2 月 19 日午前 10:18 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/4 "2019-02-19T10:18:38Z")

</div>

I was investigating a case where an upload is not deleted while it belongs to a post that has been deleted over 48 hours ago.

But … neither the `CleanUpUploads` job nor the soft deletion code for a post seem to handle this case ?

The job checks for `pu.upload_id IS NULL` but while an `Upload` has `has_many :post_uploads, dependent: :destroy` , a `Post` does not have this cascading delete?

What am I overlooking? Or is this really not handled?

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [2019 年 2 月 19 日午後 6:03 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/5 "2019-02-19T18:03:20Z")

</div>

Are you sure that upload isn’t being used elsewhere? Like in a site setting? A category image? A user avatar?

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2019 年 2 月 19 日午後 8:27 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/6 "2019-02-19T20:27:42Z")

</div>

I’m 100% sure.

```
db6033=# select * from uploads where sha1 like 'ff91%';
  id | user_id | original_filename | filesize | width | height | url | created_at | updated_at | sha1 | origin | retain_hours | extension | thumbnail_width | thumbnail_height | etag 
-------+---------+---------------------+----------+-------+--------+-------------------------------------------------------------------------------+----------------------------+----------------------------+------------------------------------------+--------+--------------+-----------+-----------------+------------------+------
 25772 | 4112 | 20190205_144913.jpg | 3233257 | 4032 | 3024 | /uploads/db6033/original/3X/f/f/ff91b693131a925a730f7db0088bc23fd002cc77.jpeg | 2019-02-13 18:44:51.075662 | 2019-02-13 18:44:51.089795 | ff91b693131a925a730f7db0088bc23fd002cc77 | | | jpeg | 666 | 500 | 

 db6033=# select * from post_uploads where upload_id=25772;
   id | post_id | upload_id 
--------+---------+-----------
 174381 | 279379 | 25772

 db6033=# select deleted_at from posts where id=279379;
         deleted_at         
----------------------------
 2019-02-16 06:53:06.366242

```

 ![image](https://global.discourse-cdn.com/meta/original/3X/e/6/e6905bbb4edfe67e829347b6c2d31fefc5518e46.png)

```
db6033=# select * from site_settings ss where NULLIF(ss.value, '')::integer = 25772 and ss.data_type = 18;
 id | name | data_type | value | created_at | updated_at 
----+------+-----------+-------+------------+------------
(0 rows)

```

When I look at the [code for CleanUpUploads](https://github.com/discourse/discourse/blob/master/app/jobs/scheduled/clean_up_uploads.rb#L47-L70) and run it manually, the upload immediately gets excluded from the result set because of the `.where("pu.upload_id IS NULL")` clause. So I decided to check where the `post_uploads ` record is being removed and the only thing I could find is in case the upload record itself is being removed. But when the post is (soft)deleted that `post_uploads ` entry is still there, and the code doesn’t check if that relates to a post record which has been (soft)deleted.

---

<div class="post-metadata">

### Author: ![zogstrip](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/zogstrip/32/512781_2.png) [@zogstrip](https://meta.discourse.org/u/zogstrip)
#### Post date: [2019 年 2 月 20 日午前 9:28 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/7 "2019-02-20T09:28:21Z")

</div>

On one hand, keeping the upload helps when restoring the post.  
On the other hand, this can _easily_ be abused.

I think we should update our `CleanUpUploads` job to remove uploads _only_ referenced in a soft-deleted post older than 1 week.

@codinghorror / @sam what do you think?

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2019 年 2 月 20 日午前 9:39 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/8 "2019-02-20T09:39:24Z")

</div>

I am traumatised from losing of uploads, my blog just lost a pile of images on early posts due to a bug we had.

I think we should simply start with a rake task people can run to reclaim the space taken up by images on deleted posts (and posts on deleted topics) we can then decide what to do longer term but at least have an outlet here.

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2019 年 2 月 20 日午後 6:00 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/9 "2019-02-20T18:00:57Z")

</div>

I’m going to play the GDPR violin here. It’s not just about reclaiming space - it’s also about being able to remove personal data. Right now many users will _think_ they removed the post including the uploads, while they didn’t. Even soft-deleting the post and hard-deleting the images would not always suffice.

I do understand @sam’s concerns though (although we keep 30 days of incremental backups I fully understand that not every Discourse forum has that luxury) so I was thinking about soft-deleting the images as well:

Would it be hard to deny the download of an image in case all posts it belongs to have been soft-deleted ? Restoring the post would make the image accessible again.

---

<div class="post-metadata">

### Author: ![codinghorror](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/codinghorror/32/110067_2.png) [@codinghorror](https://meta.discourse.org/u/codinghorror)
#### Post date: [2019 年 2 月 20 日午後 7:00 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/10 "2019-02-20T19:00:10Z")

</div>

@sam wants removal of uploads from deleted posts to be a manual rake task for now. I don’t have any particular feelings about it.

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2019 年 2 月 20 日午後 8:05 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/11 "2019-02-20T20:05:14Z")

</div>

I object to the GDPR concern, cause if you are asking for ultra strong post removal then posts need to be hard deleted, in that case uploads go as well, so what you are asking for here is a UI hard nuke.

If you must ensure image removal another simple workaround is to edit the image link out of the post

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2019 年 2 月 20 日午後 10:08 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/12 "2019-02-20T22:08:23Z")

</div>

Yeah those were two different solutions, the GDPR concern would indeed need a hard deletion, but if there are objections against that then a soft delete would be a second best.

The image link editing is a cool workaround, thanks for the tip!

---

<div class="post-metadata">

### Author: ![WorldIsMine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/worldismine/32/455660_2.png) [@WorldIsMine](https://meta.discourse.org/u/WorldIsMine)
#### Post date: [2019 年 2 月 21 日午前 6:53 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/13 "2019-02-21T06:53:46Z")

</div>

> [@sam](#):
>
> I object to the GDPR concern

I am in a situation where I can’t ignore it. On my instance, our users constantly exchange sensitive data via PM’s such as IDs and documents. They were under the impression that once deleted, they’re gone. I gave them that impression via our rules and terms, as I was mislead by the options within Discourse that state that deleted uploads are removed after X days. It turns out, they’re not. And now this all sits in our database, which will be a disaster if we ever get breached.

Would “hard nuking” as you’ve said would be something that could be implemented via a plugin? It’s not about nuking the post itself, just the attachments/uploads.

---

<div class="post-metadata">

### Author: ![sam](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/sam/32/102149_2.png) [@sam](https://meta.discourse.org/u/sam)
#### Post date: [2019 年 2 月 21 日午前 7:06 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/14 "2019-02-21T07:06:01Z")

</div>

> [@WorldIsMine](#):
>
> Would “hard nuking” as you’ve said would be something that could be implemented via a plugin? It’s not about nuking the post itself, just the attachments/uploads.

First we need the rake task, that is definitely slotted. After we have that we can also add a site setting, default off for this behavior. `purge_images_from_deleted_posts_days` something like that. Maybe we can set it to something like 1 year by default. not sure, @codinghorror can decide when we have the setting.

---

<div class="post-metadata">

### Author: ![WorldIsMine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/worldismine/32/455660_2.png) [@WorldIsMine](https://meta.discourse.org/u/WorldIsMine)
#### Post date: [2019 年 2 月 26 日午前 4:00 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/15 "2019-02-26T04:00:01Z")

</div>

So I can expect this to be implemented or do I need to find my own way?

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2019 年 2 月 26 日午前 10:00 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/16 "2019-02-26T10:00:28Z")

</div>

sam already gave a solution: if you edit the image link out of the post before deleting it then the upload will be removed after the set amount of hours.

> [@sam](#):
>
> If you must ensure image removal another simple workaround is to edit the image link out of the post

---

<div class="post-metadata">

### Author: ![WorldIsMine](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/worldismine/32/455660_2.png) [@WorldIsMine](https://meta.discourse.org/u/WorldIsMine)
#### Post date: [2019 年 2 月 27 日午前 3:34 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/17 "2019-02-27T03:34:58Z")

</div>

Oh sorry, I thought that was only a temporary workaround. OK, thank you.

---

<div class="post-metadata">

### Author: ![Falco](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/falco/32/179432_2.png) [@Falco](https://meta.discourse.org/u/Falco)
#### Post date: [2019 年 2 月 27 日午前 3:46 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/18 "2019-02-27T03:46:52Z")

</div>

A post was split to a new topic: [How to truly delete topics](https://meta.discourse.org/t/how-to-truly-delete-topics/110204)

---

<div class="post-metadata">

### Author: ![RGJ](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/rgj/32/523185_2.png) [@RGJ](https://meta.discourse.org/u/RGJ)
#### Post date: [2019 年 2 月 27 日午前 7:19 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/19 "2019-02-27T07:19:01Z")

</div>

Well, given the fact that the proposed implementation is a manual task that would only work on posts that have been removed over 1 year ago, it wouldn’t suit your purpose anyway.

So editing the image link out of the post is the second best solution (actually: the best, since it already exists and works), especially since in your use case those topics are deleted by staff.

I think we would need to diffentiate between different use cases for this:

- regular cleanup / making sure there are no illegal uploads / space issues (the rake task will suffice)
- removal for regulatory (privacy or DMCA) reasons which require uploads to be removed ASAP (editing the image links out of the posts will work, albeit cumbersome)

---

<div class="post-metadata">

### Author: ![pfaffman](https://sea3.discourse-cdn.com/meta/user_avatar/meta.discourse.org/pfaffman/32/120154_2.png) [@pfaffman](https://meta.discourse.org/u/pfaffman)
#### Post date: [2019 年 2 月 27 日午前 11:43 UTC](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231/20 "2019-02-27T11:43:56Z")

</div>

I think what you want is a plugin that destroys deleted PMs. That’s like the PMs and the uploads

[Next page](https://meta.discourse.org/t/how-to-make-an-image-orphaned-so-that-it-gets-removed/79231.md?page=2)
