npm package: @pzhiq/ptiny
Description: A CLI tool for compressing images using TinyPNG API
Latest version: 1.0.3

# @pzhiq/ptiny - TinyPNG 智能图片压缩工具

![license](https://img.shields.io/npm/l/@pzhiq/ptiny) 
![version](https://img.shields.io/npm/v/@pzhiq/ptiny)
![downloads](https://img.shields.io/npm/dt/@pzhiq/ptiny)

一款基于 TinyPNG 官方 API 开发的智能图片压缩工具，支持递归目录处理、压缩缓存和自动重试机制，帮助开发者高效优化项目中的图片资源。

---

## 📖 背景与需求

### 开发背景

现代 Web 项目常面临图片体积过大的问题，传统手动压缩方式存在以下痛点：

- 多层级目录结构需要递归处理
- 重复压缩相同文件浪费 API 调用次数
- 网络波动导致偶发性压缩失败
- 需要保留原始目录结构

### 核心能力

- ✅ **递归处理**：自动扫描子目录中的图片文件
- ✅ **智能缓存**：基于文件哈希值跳过已压缩内容
- ✅ **失败重试**：网络异常时自动重试（最多5次）
- ✅ **结构保留**：完整保持原始目录层级关系
- ✅ **安全机制**：内置 API 调用频率控制

----

## 📦 安装

```bash
npm install -g @pzhiq/ptiny
```

---

## 🛠 使用方式

### 基础命令
```bash
ptiny -s <源目录> -o <输出目录> [--key <API密钥>]
```

### 参数说明
| 参数               | 简写 | 必填 | 说明                                  |
|--------------------|------|------|---------------------------------------|
| `--source <path>` | `-s` | 是   | 待压缩的图片源目录路径                |
| `--output <path>` | `-o` | 是   | 输出目录（与源目录相同时覆盖文件）    |
| `--key <string>`  |      | 否   | TinyPNG API 密钥（支持命令行和变量传入） |

---

## 🌟 核心特性

### 文件处理流程
```mermaid
graph LR
    A[遍历源目录] --> B[计算MD5]
    B --> C{缓存比对}
    C -->|未压缩| D[调用API]
    C -->|已缓存| E[跳过]
    D --> F[保存文件]
    F --> G[更新缓存]
    D -->|失败| H[重试5次]
```

### 关键技术
1. **MD5 哈希缓存**
```javascript
// 计算文件哈希
async function calculateFileHash(filePath) {
  const content = await fs.readFile(filePath);
  return crypto.createHash('md5').update(content).digest('hex');
}
```
- 缓存文件：`.tiny-cache`（自动生成在运行目录）
- 格式：`JSON` 键值对存储文件路径与哈希值

2. **重试机制**
| 重试次数 | 等待时间 | 重试策略               |
|----------|----------|------------------------|
| 1        | 1秒      | 基础网络补偿           |
| 2        | 2秒      | 防止服务限流           |
| 3        | 3秒      | 规避临时中断           |
| 4        | 4秒      | 应对高负载延迟         |
| 5        | 5秒      | 最终失败抛出错误       |

![image-20250214101144019](/Users/manbapan/Library/Application Support/typora-user-images/image-20250214101144019.png)

---

## 📝 使用示例

### 常规压缩
```bash
# 压缩 images 目录到 optimized 目录
ptiny -s ./images -o ./optimized --key YOUR_API_KEY
```

### 覆盖原始文件
```bash
# 慎用！直接替换源文件
ptiny -s ./photos -o ./photos
```

### 递归处理演示
```bash
输入目录结构：
src/
  ├─ header.png
  └─ gallery/
       └─ photo1.jpg

输出目录结构：
dist/
  ├─ header.png
  └─ gallery/
       └─ photo1.jpg
```

---

## ⚠️ 注意事项

1. **密钥安全**
   - 通过 `--key` 参数传入
   - 内置默认密钥可能触发 API 限流

2. **缓存管理**

   ```bash
   # 强制重新压缩（清除缓存）
   rm .tiny-cache
   ```

3. **文件规则**
   - 支持格式：JPEG/PNG/WEBP（以最新的TinyPng支持格式为准）
   - 自动跳过非图片文件

4. **文件覆盖警告**

   当源目录与输出目录相同时，会**替换**原始文件

---

## ❓ 常见问题

### Q1：如何处理子目录？
工具自动递归处理所有层级的图片文件，保持原始目录结构。

### Q2：压缩失败如何排查？
控制台会输出详细错误日志，常见原因：
- API 密钥无效
- 网络连接异常
- 文件格式不受支持
- 文件夹路径异常

### Q3：如何验证压缩效果？
输出日志包含压缩详情：
```log
压缩完成! 统计信息:
----------------------------------------
总计处理图片: xx 张
成功压缩: xx 张
跳过压缩: xx 张
压缩失败: xx 张
----------------------------------------
原始总大小: xx
压缩后总大小: xx
共节省空间: xx (xx%)
```

### Q4：如何获取 API 密钥？
1. 访问 [TinyPNG API Portal](https://tinypng.com/developers)
2. 注册账号并获取密钥
3. 免费版每月 500 次压缩额度

### Q5：输出目录不存在怎么办？

工具会自动创建输出目录（包括嵌套目录）。

---

## 📜 其它信息

问题反馈：[Gitee Issue](https://gitee.com/pzhiq/ptiny/issues)  
项目源码：[Gitee仓库](https://gitee.com/pzhiq/ptiny)