上传前检查文件字节与 PNG 分辨率是否超过 30MB / 25MP,避免必失败请求浪费配额。
先看清成品
- 1×1 PNG → ok;>30MB → 失败。
- 3 项 pytest 通过。
合规提醒:Clipdrop 现属 Jasper;网页工具仍可用,API 额度/新模型以 Jasper 沟通与文档为准。只处理你有权使用的图片;勿去除水印用于侵权或伪造。输入限制常见为 30MB / 25MP(以文档为准)。本文不编造单价。
运行说明:无 Clipdrop/Jasper Image 正式密钥。A/C 用 mock 去背;对官方 clipdrop-api.co 无效密钥实测 HTTP 403。B 为本地体积预检。2026-10-23(Asia/Shanghai)pytest 通过。
做完之后你会得到什么?
| 成果 | 说明 |
|---|---|
image_limits.py |
体积预检 |
sample.png |
样例 |
test_109b.py |
测试 |
需要准备哪些环境?
| 项目 | 说明 |
|---|---|
| Python | 3.10+ |
关键事实
| 事实 | 来源 |
|---|---|
| 文档限制:≤30MB 且 ≤25 megapixels | 官方 Remove Background |
| JPEG 本脚本不解码尺寸,需外部确认 | 教程范围 |
| Jasper Image 文档同样强调 30MB/25MP | Jasper Image |
文件结构
109-clipdrop-B-src/
├── image_limits.py
├── sample.png
└── test_109b.py
第 1 步:预检脚本
#!/usr/bin/env python3
"""Pre-check image size/resolution against Clipdrop/Jasper Image soft limits (30MB, 25MP)."""
from __future__ import annotations
import argparse, json, struct, zlib
from pathlib import Path
MAX_BYTES = 30 * 1024 * 1024
MAX_MP = 25 # megapixels
def png_size(data: bytes) -> tuple[int, int] | None:
if data[:8] != b"\x89PNG\r\n\x1a\n" or len(data) < 24:
return None
# IHDR
w, h = struct.unpack(">II", data[16:24])
return int(w), int(h)
def check(path: Path) -> dict:
data = path.read_bytes()
errs = []
if len(data) > MAX_BYTES:
errs.append(f"文件 {len(data)} 字节超过 30MB")
wh = png_size(data)
mp = None
if wh:
mp = (wh[0] * wh[1]) / 1_000_000
if mp > MAX_MP:
errs.append(f"分辨率约 {mp:.1f}MP 超过 25MP")
else:
# non-PNG: only size check; note format
errs.append("无法解析 PNG IHDR;请确认 JPG/WEBP 并在上传前自行核对 ≤25MP")
# For tutorial: if it's our tiny non-parse edge — actually we only ship PNG.
# Treat missing IHDR as warning only if file is empty
if len(data) == 0:
errs.append("空文件")
else:
# downgrade: remove the format err for jpeg by checking magic
if data[:2] == b"\xff\xd8":
errs[:] = [e for e in errs if "IHDR" not in e]
errs.append("JPEG:本脚本未解码尺寸,请用外部工具确认 ≤5000×5000")
return {"ok": not errs, "bytes": len(data), "wh": wh, "mp": mp, "errors": errs}
def main(argv=None) -> int:
ap = argparse.ArgumentParser(description=__doc__)
ap.add_argument("image")
args = ap.parse_args(argv)
r = check(Path(args.image))
print(json.dumps(r, ensure_ascii=False, indent=2))
return 0 if r["ok"] else 1
if __name__ == "__main__":
raise SystemExit(main())
第 2 步:测试
from pathlib import Path
import subprocess, sys
from image_limits import check
HERE = Path(__file__).resolve().parent
def test_ok():
assert check(HERE/"sample.png")["ok"]
def test_too_big(tmp_path):
p = tmp_path / "big.bin"
p.write_bytes(b"x" * (30 * 1024 * 1024 + 1))
assert not check(p)["ok"]
def test_cli():
assert subprocess.run([sys.executable, str(HERE/"image_limits.py"), str(HERE/"sample.png")]).returncode == 0
第 3 步:运行
$ image_limits
{
"ok": true,
"bytes": 67,
"wh": [
1,
1
],
"mp": 1e-06,
"errors": []
}
$ pytest -q
... [100%]
3 passed in 0.07s
怎么检查结果?
- sample.png ok=true。
- 超大文件 errors 非空。
调试示例
手机原图 6000×4000。 约 24MP 可能擦边;先缩小再上传,比盯着 400 错误重试便宜。
常见问题
| 现象 | 原因 | 处理 |
|---|---|---|
| WEBP | 先转 PNG/查工具 | 或扩脚本 |
| 刚好 25MP | 可能被拒 | 留余量 |
| 批量 | 先预检再并发 | 注意速率限制 |
模板规则
- 超限先缩放。
- 预检进 CI。
- 保留原图备份。
项目资源
| 用途 | 地址 |
|---|---|
| Remove Background(官方) | https://clipdrop.co/apis/docs/remove-background |
| Cleanup(官方) | https://clipdrop.co/apis/docs/cleanup |
| Jasper Image 介绍 | https://images.jasper.ai/ |
先量尺寸,再花 credit。