perf: serve aliyun oss previews directly
Some checks failed
Lint / build (20) (push) Has been cancelled
Playwright Tests / test (push) Has been cancelled

This commit is contained in:
Your Name 2026-04-29 21:42:03 +08:00
parent e1e4c205e1
commit a6083ac409
8 changed files with 73 additions and 7 deletions

View File

@ -72,11 +72,13 @@ async function loadImage(url: string) {
width: MERGED_IMAGE_MAX_WIDTH,
quality: 92,
format: "png",
delivery: "proxy",
}),
buildImageProxyUrl(normalizedSource, {
width: Math.min(MERGED_IMAGE_MAX_WIDTH, 960),
quality: 86,
format: "webp",
delivery: "proxy",
}),
normalizedSource,
].filter((item): item is string => Boolean(item))

View File

@ -2742,7 +2742,10 @@ export function AgentPsdTemplateEditorDialog({
const fetchCandidates = Array.from(
new Set(
[normalizedUrl, buildImageProxyUrl(normalizedUrl)].filter(Boolean)
[
normalizedUrl,
buildImageProxyUrl(normalizedUrl, { delivery: "proxy" }),
].filter(Boolean)
)
);

View File

@ -1055,7 +1055,9 @@ export function AgentPsdTemplateExportPreview({
try {
setIsDownloading(true);
if (!shouldCompose) {
const response = await fetch(buildImageProxyUrl(imageUrl));
const response = await fetch(
buildImageProxyUrl(imageUrl, { delivery: "proxy" })
);
if (!response.ok) {
throw new Error(`下载失败(${response.status})`);
}
@ -1066,7 +1068,7 @@ export function AgentPsdTemplateExportPreview({
}
const { image, dispose } = await loadImageFromCandidates([
buildImageProxyUrl(imageUrl),
buildImageProxyUrl(imageUrl, { delivery: "proxy" }),
imageUrl,
]);

View File

@ -29,7 +29,7 @@ async function drawMarkerOnImage(
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = 'anonymous';
const loadUrl = buildImageProxyUrl(imageUrl);
const loadUrl = buildImageProxyUrl(imageUrl, { delivery: "proxy" });
img.onload = () => {
// 创建 canvas

View File

@ -1113,7 +1113,7 @@ export function RealtimeCanvasDialog({
return new Promise<HTMLImageElement>((resolve, reject) => {
const image = new Image();
const resolvedSrc = /^https?:\/\//i.test(src)
? buildImageProxyUrl(src)
? buildImageProxyUrl(src, { delivery: "proxy" })
: src;
image.crossOrigin = "anonymous";
image.onload = () => resolve(image);

View File

@ -334,7 +334,7 @@ async function drawMarkerOnImage(
return new Promise((resolve, reject) => {
const img = new Image();
img.crossOrigin = "anonymous";
const loadUrl = buildImageProxyUrl(imageUrl);
const loadUrl = buildImageProxyUrl(imageUrl, { delivery: "proxy" });
img.onload = () => {
const canvas = document.createElement("canvas");

View File

@ -108,7 +108,7 @@ export function ImageAnnotator({
(submitMode === "publish-new-canvas" ? "发布到新的画布" : "发送到新对话");
const forceDarkAppearance = appearance === "dark";
const toCanvasLoadUrl = useCallback((url: string) => {
return buildImageProxyUrl(url);
return buildImageProxyUrl(url, { delivery: "proxy" });
}, []);
const revokeObjectUrl = useCallback(() => {

View File

@ -6,6 +6,7 @@ export type ImageProxyOptions = {
width?: number;
quality?: number;
format?: ImageProxyFormat;
delivery?: "display" | "proxy";
};
function clamp(value: number, min: number, max: number): number {
@ -36,12 +37,70 @@ function isBypassUrl(url: string): boolean {
);
}
function isAliyunOssImageHost(hostname: string): boolean {
const normalized = hostname.trim().toLowerCase();
return normalized.endsWith(".aliyuncs.com") && normalized.includes(".oss-");
}
function resolveAliyunOssDisplayUrl(
url: string,
options: Pick<ImageProxyOptions, "width" | "quality" | "format">
): string | null {
let target: URL;
try {
target = new URL(url);
} catch {
return null;
}
if (!isAliyunOssImageHost(target.hostname)) {
return null;
}
if (target.searchParams.has("x-oss-process")) {
return target.toString();
}
const width = normalizeWidth(options.width);
const quality = normalizeQuality(options.quality);
const format = options.format;
if (!width && !quality && !format) {
return target.toString();
}
const processSteps = ["image"];
if (width) {
processSteps.push(`resize,w_${width}`);
}
if (quality) {
processSteps.push(`quality,q_${quality}`);
}
if (format) {
const ossFormat = format === "jpeg" ? "jpg" : format;
if (ossFormat !== "webp" && ossFormat !== "jpg" && ossFormat !== "png") {
return null;
}
processSteps.push(`format,${ossFormat}`);
}
target.searchParams.set("x-oss-process", processSteps.join("/"));
return target.toString();
}
export function buildImageProxyUrl(url: string, options: ImageProxyOptions = {}): string {
const source = String(url || "").trim();
if (isBypassUrl(source)) {
return source;
}
if (options.delivery !== "proxy") {
const directDisplayUrl = resolveAliyunOssDisplayUrl(source, options);
if (directDisplayUrl) {
return directDisplayUrl;
}
}
const width = normalizeWidth(options.width);
const quality = normalizeQuality(options.quality);
const format = options.format;