切换阿里云通用抠图正式上传链路
改用 AuthorizeFileUpload 与 Policy POST 上传临时对象 移除 GetOssStsToken、OSS V1 和 SHA-1 依赖 补充真实链路冒烟示例、单元测试与架构运维文档
This commit is contained in:
Generated
-3
@@ -4481,18 +4481,15 @@ dependencies = [
|
||||
name = "platform-matting"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"dotenvy",
|
||||
"hex",
|
||||
"hmac",
|
||||
"httpdate",
|
||||
"image",
|
||||
"platform-oss",
|
||||
"reqwest 0.12.28",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"sha1",
|
||||
"sha2",
|
||||
"time",
|
||||
"tokio",
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
//! 阿里云通用抠图在 api-server 侧的适配层。
|
||||
//!
|
||||
//! 输入 URL 策略:抠图服务只认上海地域 OSS URL,而我们没有上海地域自有 OSS,
|
||||
//! 统一由 platform-matting 上传 VIAPI 官方临时桶(1 天自动过期,无需清理)。
|
||||
//! 输入统一由 platform-matting 通过 AuthorizeFileUpload 单对象 Policy 上传动态临时 OSS。
|
||||
|
||||
use axum::http::StatusCode;
|
||||
use platform_matting::MattingError;
|
||||
@@ -108,7 +107,7 @@ mod tests {
|
||||
),
|
||||
MattingError::InvalidRequest("解析待抠图图片失败:invalid png".to_string()),
|
||||
MattingError::InvalidConfig("endpoint 为空".to_string()),
|
||||
MattingError::Sign("初始化 OSS V1 签名器失败".to_string()),
|
||||
MattingError::Sign("构造 AuthorizeFileUpload 签名失败".to_string()),
|
||||
] {
|
||||
let mapped = aliyun_matting_failure_to_app_error(&error, 3);
|
||||
|
||||
|
||||
@@ -5,13 +5,10 @@ version.workspace = true
|
||||
license.workspace = true
|
||||
|
||||
[dependencies]
|
||||
base64 = { workspace = true }
|
||||
hmac = { workspace = true }
|
||||
hex = { workspace = true }
|
||||
httpdate = { workspace = true }
|
||||
image = { workspace = true, features = ["png", "jpeg", "webp"] }
|
||||
sha1 = { workspace = true }
|
||||
reqwest = { workspace = true, features = ["json", "rustls-tls"] }
|
||||
reqwest = { workspace = true, features = ["json", "multipart", "rustls-tls"] }
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
serde_urlencoded = { workspace = true }
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
//! 通用抠图冒烟验证:本地图片 → OSS → SegmentCommonImage → 下载结果。
|
||||
//! 通用抠图冒烟验证:本地图片 → AuthorizeFileUpload 临时对象 → SegmentCommonImage → 下载结果。
|
||||
//!
|
||||
//! 运行(在 server-rs 目录下):
|
||||
//! cargo run -p platform-matting --example segment_smoke -- "C:\path\to\input.png"
|
||||
@@ -38,17 +38,16 @@ async fn main() {
|
||||
});
|
||||
let input_bytes = std::fs::read(&input_path)
|
||||
.unwrap_or_else(|error| panic!("读取测试图片失败({input_path}):{error}"));
|
||||
println!("[1/5] 已读取测试图片:{input_path}({} 字节)", input_bytes.len());
|
||||
println!(
|
||||
"[1/5] 已读取测试图片:{input_path}({} 字节)",
|
||||
input_bytes.len()
|
||||
);
|
||||
|
||||
// SegmentCommonImage 要求分辨率低于 2000x2000,超限先等比缩小。
|
||||
const MAX_EDGE: u32 = 1999;
|
||||
let decoded = image::load_from_memory(&input_bytes).expect("测试图片应可解码");
|
||||
let input_bytes = if decoded.width() > MAX_EDGE || decoded.height() > MAX_EDGE {
|
||||
let resized = decoded.resize(
|
||||
MAX_EDGE,
|
||||
MAX_EDGE,
|
||||
image::imageops::FilterType::CatmullRom,
|
||||
);
|
||||
let resized = decoded.resize(MAX_EDGE, MAX_EDGE, image::imageops::FilterType::CatmullRom);
|
||||
let mut buffer = std::io::Cursor::new(Vec::new());
|
||||
resized
|
||||
.write_to(&mut buffer, image::ImageFormat::Png)
|
||||
@@ -68,11 +67,16 @@ async fn main() {
|
||||
let http_client = reqwest::Client::new();
|
||||
|
||||
// --- 调用通用抠图 ---
|
||||
// key 优先级:VIAPI 专用 → 官方 SDK 标准命名(#IMAGE_CALL)→ 短信 key 兜底。
|
||||
// key 优先级与 api-server 配置保持一致:抠图专用 → 官方 SDK 标准命名。
|
||||
let (matting_key_id, matting_key_secret) = [
|
||||
("ALIYUN_IMAGESEG_ACCESS_KEY_ID", "ALIYUN_IMAGESEG_ACCESS_KEY_SECRET"),
|
||||
("ALIBABA_CLOUD_ACCESS_KEY_ID", "ALIBABA_CLOUD_ACCESS_KEY_SECRET"),
|
||||
("ALIYUN_SMS_ACCESS_KEY_ID", "ALIYUN_SMS_ACCESS_KEY_SECRET"),
|
||||
(
|
||||
"GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_ID",
|
||||
"GENARRATIVE_ALIYUN_MATTING_ACCESS_KEY_SECRET",
|
||||
),
|
||||
(
|
||||
"ALIBABA_CLOUD_ACCESS_KEY_ID",
|
||||
"ALIBABA_CLOUD_ACCESS_KEY_SECRET",
|
||||
),
|
||||
]
|
||||
.iter()
|
||||
.find_map(|(id_name, secret_name)| {
|
||||
@@ -86,7 +90,7 @@ async fn main() {
|
||||
})
|
||||
.expect("未找到可用的抠图 AccessKey 环境变量");
|
||||
let matting_config = MattingConfig::new(
|
||||
std::env::var("ALIYUN_IMAGESEG_ENDPOINT")
|
||||
std::env::var("GENARRATIVE_ALIYUN_MATTING_ENDPOINT")
|
||||
.unwrap_or_else(|_| DEFAULT_IMAGESEG_ENDPOINT.to_string()),
|
||||
matting_key_id,
|
||||
matting_key_secret,
|
||||
@@ -94,12 +98,12 @@ async fn main() {
|
||||
.expect("抠图配置应有效");
|
||||
let matting_client = MattingClient::new(matting_config).expect("抠图客户端应可构建");
|
||||
|
||||
// 本地 OSS 在北京地域,抠图服务要求上海地域,走 VIAPI 官方临时桶上传。
|
||||
// 非上海地域输入按新版官方 SDK 的 AdvanceRequest 口径申请单对象 Policy 后上传。
|
||||
let temp_url = matting_client
|
||||
.upload_temp_image(input_bytes, "segment-input.png", "image/png")
|
||||
.await
|
||||
.expect("上传 VIAPI 临时桶应成功");
|
||||
println!("[2/5] 已上传 VIAPI 临时桶");
|
||||
.expect("上传 AuthorizeFileUpload 临时对象应成功");
|
||||
println!("[2/5] 已上传 AuthorizeFileUpload 临时对象");
|
||||
println!("[3/5] 输入图 URL host:{}", host_of(&temp_url));
|
||||
|
||||
let result = matting_client
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user