# imgup 🖼️

> 轻量级自托管图片上传服务 — 无任何依赖，纯 Python 标准库实现

自动将上传的图片按日期归档到 `YYYY-MM-DD/` 文件夹，配合 Caddy 直接对外提供访问链接。

```
上传 photo.jpg  →  https://images.example.com/2026-07-17/photo.jpg
```

---

## ✨ 特性

- **零依赖** — 仅使用 Python 3 标准库，无需 `pip install`
- **日期归档** — 上传文件自动存入 `YYYY-MM-DD/` 子目录
- **防重名** — 同名文件自动追加 MD5 短 hash
- **Token 认证** — 简单安全的 `X-Upload-Token` 请求头鉴权
- **CORS 支持** — 可直接从网页前端调用
- **多格式支持** — jpg / png / gif / webp / svg / bmp / avif / ico
- **Shell 客户端** — 一条命令上传，自动复制链接到剪贴板

---

## 🚀 快速部署

### 1. 克隆项目

```bash
git clone https://github.com/yourusername/imgup.git
cd imgup
```

### 2. 一键安装（交互式）

```bash
bash install.sh
```

安装脚本会自动：
- 询问上传目录、域名、端口
- 生成随机 Token
- 注册并启动 systemd 服务
- 创建 `imgup` 命令到 `/usr/local/bin`

### 3. 手动安装

```bash
# 复制文件
cp server.py /opt/imgup/server.py

# 配置 systemd 服务
cp imgup.service /etc/systemd/system/imgup.service

# 修改服务配置中的变量（见下方配置说明）
nano /etc/systemd/system/imgup.service

# 启动服务
systemctl daemon-reload
systemctl enable --now imgup
```

---

## ⚙️ 配置

所有配置通过环境变量传入（在 `imgup.service` 中修改）：

| 变量 | 默认值 | 说明 |
|------|--------|------|
| `UPLOAD_DIR` | `/data/images` | 文件存储根目录 |
| `UPLOAD_TOKEN` | `change_me_please` | 上传鉴权 Token |
| `BASE_URL` | `https://images.lovecode.xin` | 返回链接的域名前缀 |
| `PORT` | `8765` | 监听端口（仅本地） |
| `MAX_SIZE_MB` | `20` | 单文件最大体积（MB） |

修改后重启服务：

```bash
systemctl daemon-reload
systemctl restart imgup
```

---

## 🌐 Caddy 配置

在 `/etc/caddy/Caddyfile` 中添加：

```caddy
images.example.com {
    encode gzip zstd

    # 上传接口代理到本地服务
    handle /upload {
        reverse_proxy 127.0.0.1:8765
    }

    # 静态文件浏览
    handle {
        root * /data/images
        file_server browse
    }
}
```

重载 Caddy：

```bash
caddy validate --config /etc/caddy/Caddyfile
systemctl reload caddy
```

---

## 📤 上传方法

### 方法一：Shell 脚本（推荐）

将 `upload.sh` 下载到本地电脑，设置 Token 后直接使用：

```bash
# 设置环境变量（加入 ~/.bashrc 或 ~/.zshrc）
export IMGUP_URL="https://images.example.com/upload"
export IMGUP_TOKEN="your_token_here"

# 上传单张
./upload.sh photo.jpg

# 批量上传
./upload.sh *.png
```

上传成功后自动复制链接到剪贴板。

### 方法二：curl

```bash
curl -X POST https://images.example.com/upload \
  -H "X-Upload-Token: your_token_here" \
  -F "file=@/path/to/image.jpg"
```

返回示例：

```json
{
  "url": "https://images.example.com/2026-07-17/photo.jpg",
  "filename": "photo.jpg",
  "date": "2026-07-17",
  "size": 204800
}
```

### 方法三：网页前端（JavaScript）

```js
async function uploadImage(file, token) {
  const form = new FormData();
  form.append("file", file);

  const res = await fetch("https://images.example.com/upload", {
    method: "POST",
    headers: { "X-Upload-Token": token },
    body: form,
  });

  const data = await res.json();
  return data.url; // https://images.example.com/2026-07-17/photo.jpg
}
```

---

## 📁 目录结构

```
/data/images/
├── 2026-07-15/
│   ├── screenshot.png
│   └── banner.jpg
├── 2026-07-16/
│   └── logo.svg
└── 2026-07-17/
    ├── photo.jpg
    └── photo_a1b2c3d4.jpg   ← 重名时自动加 hash
```

---

## 🔧 服务管理

```bash
systemctl status imgup      # 查看状态
systemctl restart imgup     # 重启服务
journalctl -u imgup -f      # 实时日志
```

---

## 📋 API 参考

| 方法 | 路径 | 说明 |
|------|------|------|
| `GET` | `/health` | 健康检查，返回服务状态 |
| `POST` | `/upload` | 上传图片（需要 Token） |

**POST /upload 请求头：**

```
Content-Type: multipart/form-data
X-Upload-Token: <your_token>
```

**POST /upload 表单字段：**

| 字段 | 类型 | 说明 |
|------|------|------|
| `file` | File | 要上传的图片文件 |

---

## 📄 License

MIT
