fix: harden compression boundaries and target search

This commit is contained in:
237899745
2026-07-25 12:23:35 +08:00
parent 0ff9eae56d
commit 61fa9cb820
9 changed files with 787 additions and 169 deletions

View File

@@ -293,7 +293,11 @@ async fn compress_json(
} else {
(saved_bytes as f64) * 100.0 / (original_size as f64)
};
let skip_charge = req.compression_rate == Some(100);
let skip_charge = req.compression_rate == Some(100)
&& req.target_size_bytes.is_none()
&& format_in == format_out
&& req.max_width.is_none()
&& req.max_height.is_none();
let charge_units = !skip_charge && compressed_size < original_size;
if charge_units {
@@ -660,7 +664,11 @@ async fn compress_direct(
} else {
(saved_bytes as f64) * 100.0 / (original_size as f64)
};
let skip_charge = req.compression_rate == Some(100);
let skip_charge = req.compression_rate == Some(100)
&& req.target_size_bytes.is_none()
&& format_in == format_out
&& req.max_width.is_none()
&& req.max_height.is_none();
let charge_units = !skip_charge && compressed_size < original_size;
if !state.config.storage_type.eq_ignore_ascii_case("local") {
@@ -893,6 +901,12 @@ async fn parse_single_file_request(multipart: &mut Multipart) -> Result<Compress
})? {
let name = field.name().unwrap_or("").to_string();
if name == "file" {
if file_bytes.is_some() {
return Err(AppError::new(
ErrorCode::InvalidRequest,
"单文件压缩接口仅允许一个 file 字段",
));
}
file_name = Some(field.file_name().unwrap_or("upload").to_string());
let bytes = field.bytes().await.map_err(|err| {
AppError::new(ErrorCode::InvalidRequest, "读取文件失败").with_source(err)
@@ -924,17 +938,13 @@ async fn parse_single_file_request(multipart: &mut Multipart) -> Result<Compress
"max_width" => {
let v = text.trim();
if !v.is_empty() {
max_width = Some(v.parse::<u32>().map_err(|_| {
AppError::new(ErrorCode::InvalidRequest, "max_width 格式错误")
})?);
max_width = Some(compress::parse_dimension(v, "max_width")?);
}
}
"max_height" => {
let v = text.trim();
if !v.is_empty() {
max_height = Some(v.parse::<u32>().map_err(|_| {
AppError::new(ErrorCode::InvalidRequest, "max_height 格式错误")
})?);
max_height = Some(compress::parse_dimension(v, "max_height")?);
}
}
"preserve_metadata" => {
@@ -971,6 +981,13 @@ async fn parse_single_file_request(multipart: &mut Multipart) -> Result<Compress
file_bytes.ok_or_else(|| AppError::new(ErrorCode::InvalidRequest, "缺少 file"))?;
let file_name = file_name.unwrap_or_else(|| "upload".to_string());
if compression_rate.is_some() && target_size_bytes.is_some() {
return Err(AppError::new(
ErrorCode::InvalidRequest,
"compression_rate 与 target_size_bytes 不能同时指定",
));
}
Ok(CompressRequest {
file_name,
file_bytes,

View File

@@ -530,13 +530,13 @@ async fn parse_batch_request(
"max_width" => {
let v = text.trim();
if !v.is_empty() {
opts.max_width = Some(match v.parse::<u32>() {
opts.max_width = Some(match compress::parse_dimension(v, "max_width") {
Ok(n) => n,
Err(_) => {
cleanup_file_paths(&files).await;
return Err(AppError::new(
ErrorCode::InvalidRequest,
"max_width 格式错误",
"max_width 必须为大于 0 的整数",
));
}
});
@@ -545,13 +545,13 @@ async fn parse_batch_request(
"max_height" => {
let v = text.trim();
if !v.is_empty() {
opts.max_height = Some(match v.parse::<u32>() {
opts.max_height = Some(match compress::parse_dimension(v, "max_height") {
Ok(n) => n,
Err(_) => {
cleanup_file_paths(&files).await;
return Err(AppError::new(
ErrorCode::InvalidRequest,
"max_height 格式错误",
"max_height 必须为大于 0 的整数",
));
}
});