# 对象存储与 WebDAV (/zh/docs/channels/object-storage)

内置对象存储模板逐个要填什么、为什么要预先建桶、公开访问地址与 302 直链、自定义模式与通用 WebDAV，以及探测失败时的报错与排查。

## 选择存储类型 [#选择存储类型]

「存储渠道」页点「新建渠道」后先选类型：

- **对象存储**：Amazon S3、Cloudflare R2、腾讯云 COS、阿里云 OSS、Backblaze B2、MinIO / 自建、S3 兼容（通用）。底层都是 rclone 的 `s3` 后端，差别只在预设的 `provider`、端点与区域。
- **网盘**：WebDAV（本页后半部分），以及需要授权的网盘（见[网盘与 OAuth](./cloud-drives.mdx)）。
- **高级**：「自定义」，直接填 rclone 后端名与参数。

模板只暴露必要字段，其余参数由模板预设。保存时按模板合并出完整的后端参数；编辑时再从已存参数反解回表单，拼进端点的字段（账户 ID、区域）也会还原。

## 对象存储模板 [#对象存储模板]

| 模板 | 需要填写 | 模板自动设置 |
|---|---|---|
| Amazon S3 | Access Key、Secret Key、区域（下拉）、存储桶 | `provider=AWS`；端点由区域推导 |
| Cloudflare R2 | Access Key、Secret Key、账户 ID、存储桶 | `provider=Cloudflare`、`region=auto`、`endpoint=https://<账户 ID>.r2.cloudflarestorage.com` |
| 腾讯云 COS | SecretId、SecretKey、区域（下拉）、存储桶 | `provider=TencentCOS`、`endpoint=cos.<区域>.myqcloud.com` |
| 阿里云 OSS | Access Key、Secret Key、区域（下拉）、存储桶 | `provider=Alibaba`、`endpoint=<区域>.aliyuncs.com` |
| Backblaze B2 | Key ID、Application Key、区域（手填）、存储桶 | `provider=Other`、`endpoint=https://s3.<区域>.backblazeb2.com` |
| MinIO / 自建 | Access Key、Secret Key、服务端点、存储桶 | `provider=Minio` |
| S3 兼容（通用）| Access Key、Secret Key、S3 API 端点、存储桶 | `provider=Other` |

每个对象存储模板还有一个可选的「公开访问地址」，见下文。字段说明：

- **存储桶**：桶名，可以接 `/前缀` 把渠道限定在桶内的一个目录，如 `my-bucket` 或 `my-bucket/imgyoung`。这个值就是渠道的存储路径。腾讯云 COS 的桶名要带 APPID 后缀，如 `mybucket-1250000000`。
- **区域**：AWS、COS、OSS 的下拉只列常用区域；阿里云的取值带 `oss-` 前缀（如 `oss-cn-hangzhou`）。所需区域不在列表里时，用「S3 兼容（通用）」手填端点。B2 的区域手填（如 `us-west-004`），要与 B2 后台显示的端点一致。
- **账户 ID**：Cloudflare 账户 ID，用来拼 R2 端点。
- **服务端点 / S3 API 端点**：完整 URL，如 `https://minio.example.com`。

## 预先建好存储桶 [#预先建好存储桶]

ImgYoung 给所有 `s3` 渠道默认加上 `no_check_bucket=true`：rclone 上传前不再检查或创建存储桶。

原因：rclone 默认会在上传前尝试创建桶。R2、MinIO 等常用的作用域凭证只对单个桶有读写权限、没有建桶权限，桶已存在时这次尝试会返回 403，导致写入失败；而周期轻探测是只读的，探不出问题，表现为「状态健康，上传却失败」。对接的桶都是预先建好的，所以默认跳过这一步。

因此：

- **先在存储商控制台建好桶**，再创建渠道。
- 凭证确有建桶权限、又想让 ImgYoung 建桶时，创建表单里打开「自动创建存储桶」：创建时尝试建一次桶（桶已存在不报错），失败则整个创建中止，返回 `渠道参数非法: 自动创建存储桶失败(请确认密钥具备建桶权限,或先在控制台建好桶并关闭此项): ` 加原因。这个开关只在创建时出现，「测试连接」不会建桶。
- 自定义模式里显式写 `no_check_bucket=false`，rclone 会恢复上传前检查并按需建桶的行为。

## 公开访问地址与 302 直链 [#公开访问地址与-302-直链]

「公开访问地址」（`public_base_url`）是可选项：存储桶（或桶前面的 CDN）对外提供公开读取的 URL 前缀，如 `https://cdn.example.com`。配置后，这个渠道才能 302 直链。

直链地址是 `<公开访问地址>/<对象键>`，对象键相对渠道的存储路径。存储桶一栏填了前缀时，公开访问地址也要对应到这个前缀：例如存储桶填 `my-bucket/imgyoung`，而 CDN 指向整个桶，公开访问地址就应写 `https://cdn.example.com/imgyoung`。末尾的 `/` 会被去掉。

一张图会被 302 跳转，需要同时满足：

1. 「设置 → 运行配置 → 访问与链接 → 访问模式」为 `redirect · 302 直链`；
2. 渠道打开了「允许 302 直链」，且未加密；
3. 渠道配置了公开访问地址；
4. 渠道健康，这张图在它上面的副本已就绪，并且是按优先级排在最前的满足上述条件的渠道。

任一条件不满足就走代理。打开「允许 302 直链」却没填公开访问地址时，表单提示「未配置 public_base_url，302 直链不会生效，访问将回落代理」。

302 响应带 `Cache-Control: no-store`，浏览器与 CDN 都不缓存这次跳转，渠道切换、下线或图片到期后立即生效。对象写入渠道时按内容识别图片类型并设好 `Content-Type`，对象键虽然不带扩展名，浏览器直接打开直链也能正常显示。

存储桶的公开读权限要在存储商处自行开启，ImgYoung 不做检查。公开可读意味着拿到直链的人可以绕过 ImgYoung 直接访问对象，防盗链只对经过 ImgYoung 的请求生效。访问模式的完整说明见[访问与链接](../guides/access.mdx)。

## 自定义模式 [#自定义模式]

「高级 → 自定义」直接填写 rclone 后端名与参数，适合模板没有覆盖的后端（rclone 的任意后端都可用，如 `sftp`、`ftp`、`azureblob`、另一块磁盘上的 `local`）。

- **rclone 驱动**：后端名，即 `rclone.conf` 里 `type` 的值，如 `s3`、`sftp`、`local`。
- **后端参数**：键值对，键是该后端的选项名，与 `rclone.conf` 里的写法一致，只允许字母、数字与下划线。从 `rclone config show` 的输出里照抄即可（`type` 一行填到「rclone 驱动」）。
- 两个约定键不交给 rclone：`path` 是后端内的存储路径（桶名及前缀，或目录）；`public_base_url` 是公开访问地址。`local` 后端不填 `path` 时使用 `<数据目录>/blobs`。

密码类参数（rclone 标记为密码的选项，如 `sftp`、`ftp`、`webdav` 的 `pass`）在 rclone 里要以编码后的形式保存。ImgYoung 自动处理：填明文会被编码；已经是编码结果的值（例如从 `rclone.conf` 复制来的）原样保留。极少数明文密码恰好形似编码结果，会被原样放过，表现为认证失败；遇到这种情况先执行 `rclone obscure <密码>`，把输出填进去。

```text title="示例:SFTP 渠道"
rclone 驱动   sftp
后端参数      host = files.example.com
              user = imgyoung
              pass = <密码>
              path = /srv/imgyoung
```

## WebDAV [#webdav]

通用 WebDAV 模板在选类型的「网盘」分组里，覆盖坚果云、Nextcloud / ownCloud、群晖、Alist 等。这些服务底层都是 rclone 的 `webdav` 后端，只是服务地址与「服务类型」不同，所以只有一个模板。

| 字段 | 说明 |
|---|---|
| 服务地址 | WebDAV 根地址。坚果云 `https://dav.jianguoyun.com/dav/`；Nextcloud / ownCloud `https://域名/remote.php/dav/files/用户名/`；Alist `https://域名/dav/`；群晖 `https://域名:5006/` |
| 服务类型 | 选错会导致列目录或分片上传行为异常；拿不准选「其他（坚果云 / Alist / 群晖等）」 |
| 用户名 | WebDAV 账号 |
| 密码 | 坚果云必须用「应用密码」，不能用登录密码，在坚果云的安全选项里生成 |
| 存储目录 | 服务内用于存放图片的目录，默认提示 `imgyoung`；留空存放在根目录 |

「服务类型」的选项与 rclone `vendor` 参数的对应：

| 选项 | `vendor` |
|---|---|
| Nextcloud | `nextcloud` |
| ownCloud 10 | `owncloud` |
| ownCloud Infinite Scale | `infinitescale` |
| SharePoint Online | `sharepoint` |
| SharePoint（NTLM 自建）| `sharepoint-ntlm` |
| Fastmail Files | `fastmail` |
| rclone serve webdav | `rclone` |
| 其他（坚果云 / Alist / 群晖等）| `other` |

WebDAV 渠道没有公开访问地址，表单里也不显示「允许 302 直链」与「自动创建存储桶」，访问始终走代理。阿里云盘、百度网盘等国内网盘也通过 WebDAV 接入，做法见[网盘与 OAuth](./cloud-drives.mdx)。

## 常见报错与排查 [#常见报错与排查]

「测试连接」的失败原因，以及渠道状态列「异常」的悬停原因，都按底层错误的特征翻译成下表的提示（不区分大小写，自上而下匹配第一条）；无法归类的错误显示原文的前 200 个字符，「测试连接」还会抹掉其中的凭证（rclone 标记为密码或敏感信息的参数值）。

| 提示 | 底层错误特征 | 排查 |
|---|---|---|
| `认证失败(403):检查 Access Key / Secret Key 及其权限` | `InvalidAccessKeyId`、`SignatureDoesNotMatch`、`StatusCode: 403`（只出现在 S3 类后端）| 核对密钥是否抄错、是否已吊销，以及是否对这个桶有读、写、删权限。只读密钥会在深探测的写入环节失败 |
| `应用凭证无效:检查 Client ID / Client Secret 是否与签发令牌的应用一致` | `invalid_client`、`unauthorized_client` | 网盘渠道的「应用 Client ID」「应用 Client Secret」填错，或与签发令牌的应用不是同一个 |
| `授权已失效:刷新令牌被拒绝,请重新授权` | `invalid_grant` | 令牌被吊销或已过期太久，在编辑表单里点「重新授权」 |
| `认证失败(401):检查用户名、密码或授权令牌是否有效` | `401 Unauthorized`、`unauthenticated`、`InvalidAuthenticationToken` | WebDAV 的用户名或密码（坚果云要用应用密码），或网盘的授权令牌 |
| `无访问权限(403):检查账号对存储位置的权限` | `AccessDenied`、`access denied`、`403 Forbidden` | 非 S3 后端的账号对存储目录没有读、写或删权限 |
| `存储桶不存在或无权访问:检查桶名与凭证权限` | `NoSuchBucket`、`no such bucket`、`BucketRegionError` | 核对桶名（COS 带 APPID 后缀）；确认桶已建好 |
| `区域不匹配:检查所选区域与存储桶实际所在区域` | `PermanentRedirect`、`AuthorizationHeaderMalformed` | 区域或端点与桶的实际区域不一致 |
| `无法解析服务端点域名:检查 endpoint 配置` | `no such host`、`server misbehaving` | 端点拼写错误，或服务器 DNS 不通 |
| `无法连接服务端点:检查 endpoint 地址与端口` | `connection refused`、`connection reset` | 端口、协议或防火墙问题 |
| `TLS 证书校验失败:检查端点证书或改用正确协议` | `certificate`、`x509`、`tls handshake` | 自签证书，或把 `http` 服务写成了 `https` |
| `连接超时:检查端点地址与网络连通性` | 超时（含探测自身的 10 / 20 秒超时）| 网络不通或服务过慢 |
| `存储路径无写入权限:检查目录权限` | `permission denied`、`read-only file system` | `local` 渠道的目录权限；容器内以 uid 65532 运行时，挂载目录要对它可写 |

保存表单时的常见拒绝（提交即返回，不会建出渠道）：

| 提示 | 原因 |
|---|---|
| `渠道参数非法: 字段 <key> 必填` | 模板必填字段为空，字段以 key 指称，如 `渠道参数非法: 字段 bucket 必填` |
| `渠道名已存在` | 渠道名重复（409）|
| `渠道参数非法: 初始化 rclone 后端 "…": …` | 用填写的参数试构造后端失败，原因见冒号后的 rclone 原文 |
| `渠道参数非法: 未知的 rclone 后端 "…"` | 自定义模式的驱动名拼错 |
| `渠道参数非法: 配置键 "…" 非法(仅允许字母数字下划线)` | 自定义参数的键含其他字符（如 `-`）|
| `渠道参数非法: 自动创建存储桶失败(…)` | 打开了「自动创建存储桶」，但凭证没有建桶权限 |
| `渠道参数非法: 后端 "onedrive" 授权后的配置失败: …` | 新授权的 OneDrive 渠道选定驱动器时向服务商查询失败 |
| `渠道参数非法: 字段 "…" 不是凭证,不能沿用已存值` | 掩码值 `__imgyoung_secret_keep__` 填在了不属于凭证的参数上 |
| `渠道参数非法: 字段 "…" 无已存原值可保留,请重新填写` | 提交了掩码值，但该参数在已存配置里没有值 |

渠道已建好但状态为「异常」时，改好配置后在行菜单点「重新探测」，它会立即做一次深探测并刷新状态。探测与状态的规则见[渠道与容灾](./index.mdx)。
