export const compressPic = (url: string): Promise<string> => {
return new Promise((resolve) => {
const sys = uni.getSystemInfoSync();
const isAndroid = sys.platform === "android";
// 目标大小区间 (KB)
const MIN_SIZE = 10;
const MAX_SIZE = isAndroid ? 100 : 20;
// 最大重试次数,防止死循环
const MAX_RETRIES = 6;
if (!url) {
resolve(DEFAULT_SHARE_IMG);
return;
}
if (isAndroid) {
resolve(url);
return;
}
// 获取文件大小 (KB)
const getFileSize = (filePath: string): Promise<number> => {
return new Promise((res) => {
uni.getFileInfo({
filePath,
success: (info) => {
res(info.size / 1024);
},
fail: () => {
res(0);
},
});
});
};
// 递归压缩核心逻辑
const recursiveCompress = (
src: string,
currentWidth: number,
currentQuality: number,
retryCount: number
) => {
// 超过最大重试次数,如果还是太大,直接返回兜底图,避免分享失败
if (retryCount > MAX_RETRIES) {
console.warn(`压缩次数过多,放弃压缩,使用兜底图`);
resolve(DEFAULT_SHARE_IMG);
return;
}
console.log(
`第 ${
retryCount + 1
} 次压缩: 宽 ${currentWidth}, 质量 ${currentQuality}`
);
uni.compressImage({
src,
quality: currentQuality,
compressedWidth: currentWidth,
success: async (res) => {
const tempPath = res.tempFilePath;
const size = await getFileSize(tempPath);
console.log(`当前体积: ${size.toFixed(2)}KB`);
if (size <= MAX_SIZE) {
// 1. 完美:小于 20KB
if (size >= MIN_SIZE) {
console.log("压缩完美达标");
resolve(tempPath);
} else {
// 2. 有点太小了(小于10KB),但也接受,毕竟越小越好,直接返回
console.log("压缩结果小于10KB,直接使用");
resolve(tempPath);
}
} else {
// 3. 还是太大 (> 20KB),继续压缩
// 策略:优先降质量,质量太低了再降尺寸
let nextQuality = currentQuality;
let nextWidth = currentWidth;
nextQuality = currentQuality - 15;
if (nextQuality < 30) {
nextQuality = 50; // 重置质量
nextWidth = Math.floor(currentWidth * 0.8); // 尺寸缩小20%
}
if (nextWidth < 200) nextWidth = 200;
// 递归调用
recursiveCompress(
isAndroid ? src : tempPath,
nextWidth,
nextQuality,
retryCount + 1
);
}
},
fail: (err) => {
console.error("压缩API失败", err);
resolve(DEFAULT_SHARE_IMG);
},
});
};
// 初始入口
const startCompress = (src: string) => {
getFileSize(src).then((size) => {
console.log(`【Debug】原始图片体积: ${size.toFixed(2)}KB`);
});
uni.getImageInfo({
src,
success: (imageInfo) => {
// 初始策略:基准宽度 300px,初始质量 80
const baseWidth = 300;
const baseQuality = isAndroid ? 92 : 80;
const startWidth =
imageInfo.width > baseWidth ? baseWidth : imageInfo.width;
recursiveCompress(src, startWidth, baseQuality, 0);
},
fail: () => {
resolve(DEFAULT_SHARE_IMG);
},
});
};
// 下载或直接处理
if (url.startsWith("http") || url.startsWith("https")) {
uni.downloadFile({
url,
success: (res) => {
if (res.statusCode === 200) {
startCompress(res.tempFilePath);
} else {
resolve(DEFAULT_SHARE_IMG);
}
},
fail: () => {
resolve(DEFAULT_SHARE_IMG);
},
});
} else {
startCompress(url);
}
});
};




吹风机 (作者)
图片是网络图 不是选择的
2025-12-12 18:27