| | |
| | | * 压缩图片到体积限制内。 |
| | | */ |
| | | const ensureImageSizeUnderLimit = useCallback(async (filePath: string) => { |
| | | // iOS 端 Taro.compressImage 仅支持 JPG/JPEG,其他格式直接使用原图上传。 |
| | | if (!/\.(?:jpe?g)(?:[?#].*)?$/i.test(filePath)) { |
| | | return filePath; |
| | | } |
| | | const sizeLimitBytes = options.imageSizeLimitBytes || DEFAULT_IMAGE_SIZE_LIMIT_BYTES; |
| | | try { |
| | | let currentFilePath = filePath; |
| | | const currentSize = await getFileSize(currentFilePath); |
| | | const originalFilePath = filePath; |
| | | let lastCompressedFilePath = filePath; |
| | | const currentSize = await getFileSize(originalFilePath); |
| | | if (currentSize <= sizeLimitBytes) { |
| | | return currentFilePath; |
| | | return originalFilePath; |
| | | } |
| | | for (const quality of IMAGE_COMPRESS_QUALITIES) { |
| | | try { |
| | | // 每次都基于原图压缩,避免 80 -> 60 -> 40 的代际压缩导致画质累积劣化。 |
| | | const compressResult: any = await Taro.compressImage({ |
| | | src: currentFilePath, |
| | | src: originalFilePath, |
| | | quality |
| | | }); |
| | | const compressedPath = compressResult?.tempFilePath || currentFilePath; |
| | | const compressedPath = compressResult?.tempFilePath; |
| | | if (!compressedPath) { |
| | | continue; |
| | | } |
| | | lastCompressedFilePath = compressedPath; |
| | | const compressedSize = await getFileSize(compressedPath); |
| | | currentFilePath = compressedPath; |
| | | if (compressedSize <= sizeLimitBytes) { |
| | | return currentFilePath; |
| | | return compressedPath; |
| | | } |
| | | } catch (error) { |
| | | // 单次压缩失败时继续尝试更低质量。 |
| | | // 单次压缩失败时继续基于原图尝试更低质量。 |
| | | } |
| | | } |
| | | return currentFilePath; |
| | | return lastCompressedFilePath; |
| | | } catch (error) { |
| | | return filePath; |
| | | } |