diff --git a/src/components/UploadCover/upload-from-wx.tsx b/src/components/UploadCover/upload-from-wx.tsx index d643b2f..ce84202 100644 --- a/src/components/UploadCover/upload-from-wx.tsx +++ b/src/components/UploadCover/upload-from-wx.tsx @@ -15,7 +15,7 @@ export interface UploadFromWxProps { async function convert_to_jpg_and_compress( src: string, - { width, height } + { width, height, quality }: { width: number; height: number; quality: number } ): Promise { const canvas = Taro.createOffscreenCanvas({ type: "2d", width, height }); const ctx = canvas.getContext("2d") as CanvasRenderingContext2D; @@ -33,22 +33,54 @@ async function convert_to_jpg_and_compress( return new Promise((resolve, reject) => { Taro.canvasToTempFilePath({ canvas: canvas as unknown as Taro.Canvas, - fileType: "png", - quality: 0.7, + fileType: "jpg", + quality, success: (res) => resolve(res.tempFilePath), fail: reject, }); }); } +function getFileSize(path: string): Promise { + const fs = (Taro as any).getFileSystemManager(); + return new Promise((resolve, reject) => { + fs.stat({ + path, + success: (res) => resolve(res.stats.size), + fail: reject, + }); + }); +} + async function compressImage(files) { const res: string[] = []; + const qualityList = [0.9, 0.85, 0.8, 0.75, 0.7, 0.65, 0.6]; + for (const file of files) { - const compressed_image = await convert_to_jpg_and_compress(file.path, { - width: file.width, - height: file.height, - }); - res.push(compressed_image); + // 小图且体积已在目标范围内时,直接上传原图,避免二次压缩变糊 + if ( + file.size <= TARGET_IMAGE_SIZE && + file.width <= IMAGE_MAX_SIZE.width && + file.height <= IMAGE_MAX_SIZE.height + ) { + res.push(file.path); + continue; + } + + let bestImage = file.path; + for (const quality of qualityList) { + const compressedImage = await convert_to_jpg_and_compress(file.path, { + width: file.width, + height: file.height, + quality, + }); + const compressedSize = await getFileSize(compressedImage); + bestImage = compressedImage; + if (compressedSize <= TARGET_IMAGE_SIZE) { + break; + } + } + res.push(bestImage); } return res; } @@ -58,6 +90,8 @@ const IMAGE_MAX_SIZE = { width: 1080, height: 720, }; +// 压缩目标体积(约 300KB) +const TARGET_IMAGE_SIZE = 800 * 1024; // 标准长宽比,判断标准 const STANDARD_ASPECT_RATIO = IMAGE_MAX_SIZE.width / IMAGE_MAX_SIZE.height;