调整验证码图片大小
This commit is contained in:
@@ -1,8 +1,8 @@
|
||||
FROM python:3.10-slim
|
||||
|
||||
# 系统依赖(python-magic 需要 libmagic)
|
||||
# 系统依赖(python-magic 需要 libmagic,验证码需要清晰字体)
|
||||
RUN apt-get update && \
|
||||
apt-get install -y --no-install-recommends libmagic1 && \
|
||||
apt-get install -y --no-install-recommends libmagic1 fonts-dejavu-core && \
|
||||
rm -rf /var/lib/apt/lists/*
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
@@ -38,6 +38,16 @@ NAME_REGEX = re.compile(r'^[\u4e00-\u9fa5a-zA-Z0-9_]{2,20}$')
|
||||
# 文件名中不安全的字符
|
||||
UNSAFE_FILENAME_CHARS = re.compile(r'[<>:"/\\|?*\x00-\x1f]')
|
||||
|
||||
# 验证码图片参数
|
||||
CAPTCHA_IMAGE_SIZE = (320, 100)
|
||||
CAPTCHA_FONT_SIZE = 68
|
||||
CAPTCHA_FONT_PATHS = (
|
||||
"/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf",
|
||||
"/usr/local/share/fonts/DejaVuSans-Bold.ttf",
|
||||
"/System/Library/Fonts/Supplemental/Arial Bold.ttf",
|
||||
"/System/Library/Fonts/Supplemental/Verdana Bold.ttf",
|
||||
)
|
||||
|
||||
|
||||
# ── 工具函数 ────────────────────────────────────────────────────────
|
||||
def sanitize_name(name: str) -> str | None:
|
||||
@@ -88,9 +98,25 @@ def generate_captcha_text(length: int = 4) -> str:
|
||||
return ''.join(random.choices(chars, k=length))
|
||||
|
||||
|
||||
def load_captcha_font(size: int = CAPTCHA_FONT_SIZE) -> ImageFont.ImageFont:
|
||||
"""加载适合验证码的大号字体,兼容 Linux/Docker 和 macOS 本地环境"""
|
||||
for font_path in CAPTCHA_FONT_PATHS:
|
||||
if not os.path.exists(font_path):
|
||||
continue
|
||||
try:
|
||||
return ImageFont.truetype(font_path, size)
|
||||
except OSError:
|
||||
continue
|
||||
|
||||
try:
|
||||
return ImageFont.truetype("DejaVuSans-Bold.ttf", size)
|
||||
except OSError:
|
||||
return ImageFont.load_default(size=size)
|
||||
|
||||
|
||||
def generate_captcha_image(text: str) -> Image.Image:
|
||||
"""生成验证码图片(含干扰线和噪点)"""
|
||||
width, height = 320, 100
|
||||
width, height = CAPTCHA_IMAGE_SIZE
|
||||
# 浅色随机背景
|
||||
bg_color = (random.randint(235, 255), random.randint(235, 255), random.randint(235, 255))
|
||||
image = Image.new('RGB', (width, height), bg_color)
|
||||
@@ -109,15 +135,15 @@ def generate_captcha_image(text: str) -> Image.Image:
|
||||
dot_color = (random.randint(140, 200), random.randint(140, 200), random.randint(140, 200))
|
||||
draw.point((x, y), fill=dot_color)
|
||||
|
||||
# 绘制文字
|
||||
try:
|
||||
font = ImageFont.truetype("/usr/share/fonts/truetype/dejavu/DejaVuSans-Bold.ttf", 65)
|
||||
except OSError:
|
||||
font = ImageFont.load_default()
|
||||
font = load_captcha_font()
|
||||
char_slot_width = width // len(text)
|
||||
|
||||
for i, char in enumerate(text):
|
||||
x = 20 + i * 72
|
||||
y = random.randint(6, 18)
|
||||
bbox = draw.textbbox((0, 0), char, font=font)
|
||||
char_width = bbox[2] - bbox[0]
|
||||
char_height = bbox[3] - bbox[1]
|
||||
x = i * char_slot_width + (char_slot_width - char_width) // 2 - bbox[0] + random.randint(-4, 4)
|
||||
y = (height - char_height) // 2 - bbox[1] + random.randint(-5, 5)
|
||||
color = (random.randint(0, 80), random.randint(0, 80), random.randint(0, 80))
|
||||
draw.text((x, y), char, font=font, fill=color)
|
||||
|
||||
|
||||
@@ -610,8 +610,11 @@ input[type="text"].input-error {
|
||||
}
|
||||
|
||||
.modal-captcha-img {
|
||||
height: 46px;
|
||||
flex: 1;
|
||||
height: 86px;
|
||||
width: min(260px, 100%);
|
||||
max-width: 260px;
|
||||
min-width: 0;
|
||||
flex: 1 1 0;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1.5px solid var(--border);
|
||||
cursor: pointer;
|
||||
@@ -721,6 +724,11 @@ input[type="text"].input-error {
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.modal-captcha-img {
|
||||
height: 72px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@@ -610,9 +610,11 @@ input[type="text"].input-error {
|
||||
}
|
||||
|
||||
.modal-captcha-img {
|
||||
height: 80px;
|
||||
width: 240px;
|
||||
flex: none;
|
||||
height: 86px;
|
||||
width: min(260px, 100%);
|
||||
max-width: 260px;
|
||||
min-width: 0;
|
||||
flex: 1 1 0;
|
||||
border-radius: var(--radius-sm);
|
||||
border: 1.5px solid var(--border);
|
||||
cursor: pointer;
|
||||
@@ -722,6 +724,11 @@ input[type="text"].input-error {
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.modal-captcha-img {
|
||||
height: 72px;
|
||||
max-width: 100%;
|
||||
}
|
||||
|
||||
.form-actions {
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user