feat: 支持按目标大小压缩图片

- 新增 target_size_bytes 参数,支持直接指定压缩后的目标大小(字节)
- 实现自动缩放算法:当仅调整质量无法达到目标时,自动缩小图片尺寸
- 前端新增压缩模式切换:百分比模式 / 目标大小模式
- 支持 KB/MB 单位选择
- 优化二分搜索算法,提高目标大小的精准度

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
2026-01-10 17:51:15 +08:00
parent df9c40e456
commit 5f432998a3
5 changed files with 288 additions and 27 deletions

View File

@@ -54,6 +54,7 @@ struct CompressRequest {
file_bytes: Vec<u8>,
level: CompressionLevel,
compression_rate: Option<u8>,
target_size_bytes: Option<u64>, // 新增:直接指定目标大小(字节)
output_format: Option<ImageFmt>,
max_width: Option<u32>,
max_height: Option<u32>,
@@ -246,6 +247,7 @@ async fn compress_json(
format_out,
effective_level,
req.compression_rate,
req.target_size_bytes, // 新增:目标大小
req.max_width,
req.max_height,
req.preserve_metadata,
@@ -603,6 +605,7 @@ async fn compress_direct(
format_out,
effective_level,
req.compression_rate,
req.target_size_bytes, // 新增:目标大小
req.max_width,
req.max_height,
req.preserve_metadata,
@@ -835,6 +838,7 @@ async fn parse_single_file_request(multipart: &mut Multipart) -> Result<Compress
let mut level = CompressionLevel::Medium;
let mut output_format: Option<ImageFmt> = None;
let mut compression_rate: Option<u8> = None;
let mut target_size_bytes: Option<u64> = None; // 新增
let mut max_width: Option<u32> = None;
let mut max_height: Option<u32> = None;
let mut preserve_metadata = false;
@@ -905,6 +909,24 @@ async fn parse_single_file_request(multipart: &mut Multipart) -> Result<Compress
"1" | "true" | "yes" | "y" | "on"
);
}
"target_size_bytes" | "target_size" => {
let v = text.trim();
if !v.is_empty() {
target_size_bytes = Some(
v.parse::<u64>()
.map_err(|_| AppError::new(ErrorCode::InvalidRequest, "target_size_bytes 格式错误,需为正整数(字节)"))?,
);
// 最小目标大小限制1KB
if let Some(size) = target_size_bytes {
if size < 1024 {
return Err(AppError::new(
ErrorCode::InvalidRequest,
"target_size_bytes 最小为 10241KB",
));
}
}
}
}
_ => {}
}
}
@@ -917,6 +939,7 @@ async fn parse_single_file_request(multipart: &mut Multipart) -> Result<Compress
file_bytes,
level,
compression_rate,
target_size_bytes, // 新增
output_format,
max_width,
max_height,