# Cloudflare Image Uploader [中文说明](README.zh.md) When you clip a web article, its images still live on someone else's website. If the author deletes the post, the images in your note are gone. This plugin downloads those images, keeps them in your own Cloudflare R2 (Cloudflare's cloud storage: free up to 10 GB, no charge for viewing), and changes the image links in your note to your copies. The original site can delete them; yours stay. Images you paste or drag into a note are uploaded too. ## What it does - **Saves images after you clip**: a few seconds after a new note appears (clipped, or synced from another device), its web images are saved. This switch is set on each device separately; turning it on on one computer that's usually on is enough. - **Saves images after you copy and paste from a web page.** - **Saves on demand**: the current note, or all notes at once. Images that can't be downloaded (deleted, or the site won't allow it) are left as they are and listed at the end. - **Can switch back**: the original address of every image is remembered; *Restore original web links in current note* puts them back. - **Uploads pasted and dropped images.** Without internet, they're kept in the vault and uploaded later. - **Uploads images already in your vault** (current note or the whole vault), keeping their display size and caption. - Each image is stored only once. Optionally converts images to the smaller WebP format (animations are left alone). - Never deletes anything from your storage. - Works on computers and phones. ## Setup 1. Cloudflare dashboard → R2 → **Create bucket** (a bucket is where your images go). 2. Open the bucket → Settings → **Custom Domains**: connect a domain you have on Cloudflare, e.g. `img.example.com`. Image links will start with it. The built-in `r2.dev` address is throttled and only meant for trying things out. 3. R2 → **Manage API tokens** → Create Account API token, permission *Object Read & Write*, for this bucket only. You'll get two keys. 4. Obsidian → Settings → Cloudflare Image Uploader: enter the Account ID, bucket name, the two keys and the address from step 2, then click **Test connection**. 5. For automatic saving, turn it on under *Web images*. ## Commands Press Ctrl+P (Cmd+P on Mac) and search. The two whole-vault ones are also under *Tools* in the settings. | Command | What it does | |---|---| | Save web images in current note to R2 | Saves the web images in this note | | Save web images in all notes to R2… | Same for all notes; tells you how many first | | Upload local images in current note | Uploads this note's local images | | Upload all local images in vault… | Same for all notes; tells you how many first | | Retry failed uploads | Uploads images that didn't make it earlier, right now | | Restore original web links in current note | Puts the original addresses back; your copies stay in storage | | Stop the running job | Stops after the current note; run the command again to continue | After an image fails to download twice, automatic saving stops trying it (commands still try; the record can be cleared in settings). A busy site or a bad connection doesn't count as a failure. Local images are kept after upload. If you choose *Move to trash*, only images no note uses any more are removed. ## File names Default `{hash}.{ext}`: the name comes from the image's content, so the same image always gets the same name and is never uploaded twice. You can change it: `{name}` original file name, `{year}` `{month}` `{day}` date, `{timestamp}` time, `{ext}` extension, `{hash:N}` first N characters only. Slashes make folders, e.g. `notes/{year}/{month}/{hash}.{ext}`. Without `{hash}`, a file with the same name is never overwritten; the time is added to the name instead. ## Privacy and security - The plugin only connects to your R2, your image address, and the sites the images in your notes come from. It collects no data. - **Anyone with the link can see an uploaded image.** But nobody can list all your images, and the generated names can't be guessed. - Keys are stored only on the current device, so you enter them once per device. *Sync keys with the vault* writes them unencrypted into the plugin's `data.json`, which syncs with your vault. Only turn it on if your sync is private. Give the token access to the image bucket only. - Saved images are for your own archive; respect the authors' rights. ## Development ```bash npm install npm run dev # rebuild on change npm test # tests npm run build # check + production build npm run install-vault -- /path/to/vault ``` `test/r2.e2e.test.ts` tests against a real bucket when `.env.local` has `R2_ACCOUNT_ID`, `R2_BUCKET`, `R2_PUBLIC_URL`, `R2_ACCESS_KEY_ID`, `R2_SECRET_ACCESS_KEY`. Release: bump the version in `manifest.json`, `package.json` and `versions.json`, `npm run build`, then: ```bash gh release create 1.0.1 main.js manifest.json styles.css --title 1.0.1 --notes "..." ``` ## License MIT