Flutter图片压缩报错:Instance of 'CompressError'问题求助
解决Flutter图片压缩中的CompressError问题
问题重现
使用Flutter的flutter_image_compress库实现图片压缩时,调用_compressImage()函数抛出CompressError异常,相关代码及错误日志如下:
压缩函数代码
Future<void> _compressImage() async { if (_image == null) { return; } final originalSize = _originalSize ?? await _image!.length(); final compressedImage = await FlutterImageCompress.compressAndGetFile( _image!.path, _image!.path, quality: 60, ); final compressedSize = await compressedImage!.length(); setState(() { _image = compressedImage; _compressedSize = compressedSize; }); print('Original Size =====> $originalSize'); print('Compressed Size =====> $compressedSize'); }
图片选择及变量定义代码
XFile? _image; int? _originalSize; int? _compressedSize; late XFile pickedImage; Future<void> _pickImageCamera() async { final picker = ImagePicker(); final pickedImage = await picker.pickImage(source: ImageSource.camera); if (pickedImage != null) { final XFile image = XFile(pickedImage.path); final originalSize = await image.length(); setState(() { _image = image; _originalSize = originalSize; _compressedSize = null; }); } }
错误日志
E/flutter (21267): [ERROR:flutter/runtime/dart_vm_initializer.cc(41)] Unhandled Exception: Instance of 'CompressError' E/flutter (21267): #0 FlutterImageCompressCommon.compressAndGetFile (package:flutter_image_compress_common/flutter_image_compress_common.dart:173:7) E/flutter (21267): #1 FlutterImageCompress.compressAndGetFile (package:flutter_image_compress/flutter_image_compress.dart:105:22) E/flutter (21267): #2 _ImageCompressorState._compressImage (package:ezy_img_compressor/image_compressor.dart:52:56) E/flutter (21267): #3 _InkResponseState.handleTap (package:flutter/src/material/ink_well.dart:1154:21) E/flutter (21267): #4 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:275:24) E/flutter (21267): #5 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:654:11) E/flutter (21267): #6 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:311:5) E/flutter (21267): #7 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:281:7) E/flutter (21267): #8 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:167:27) E/flutter (21267): #9 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:469:20) E/flutter (21267): #10 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:445:22) E/flutter (21267): #11 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:331:11) E/flutter (21267): #12 GestureBinding._handlePointerEventImmediately (package:flutter/src/gestures/binding.dart:400:7) E/flutter (21267): #13 GestureBinding.handlePointerEvent (package:flutter/src/gestures/binding.dart:363:5) E/flutter (21267): #14 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:320:7) E/flutter (21267): #15 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:293:9) E/flutter (21267): #16 _invoke1 (dart:ui/hooks.dart:158:13) E/flutter (21267): #17 PlatformDispatcher._dispatchPointerDataPacket (dart:ui/platform_dispatcher.dart:382:7) E/flutter (21267): #18 _dispatchPointerDataPacket (dart:ui/hooks.dart:91:31)
错误原因分析
- 路径冲突:
compressAndGetFile函数中输入与输出路径完全相同,压缩时无法同时读取原文件并写入新文件,触发文件访问冲突。 - 空值风险:直接使用
compressedImage!强制解包,若压缩失败会导致空指针异常,加剧程序崩溃。
修复方案
修改后的压缩函数
Future<void> _compressImage() async { if (_image == null) { return; } try { final originalSize = _originalSize ?? await _image!.length(); // 生成独立的输出路径,避免与原文件冲突 final outputPath = _image!.path.replaceAll(RegExp(r'\.(jpg|jpeg|png)$'), '_compressed.$1'); final compressedImage = await FlutterImageCompress.compressAndGetFile( _image!.path, outputPath, quality: 60, ); if (compressedImage != null) { final compressedSize = await compressedImage.length(); setState(() { _image = compressedImage; _compressedSize = compressedSize; }); print('Original Size =====> $originalSize'); print('Compressed Size =====> $compressedSize'); } else { print('压缩失败:未生成压缩文件'); } } catch (e) { print('压缩异常:$e'); } }
优化后的图片选择函数(可选)
XFile? _image; int? _originalSize; int? _compressedSize; Future<void> _pickImageCamera() async { final picker = ImagePicker(); final pickedImage = await picker.pickImage(source: ImageSource.camera); if (pickedImage != null) { final originalSize = await pickedImage.length(); setState(() { _image = pickedImage; _originalSize = originalSize; _compressedSize = null; }); } }
关键优化说明
- 独立输出路径:通过正则替换为原文件名添加
_compressed后缀,确保压缩文件与原文件路径不冲突。 - 异常捕获:用
try-catch包裹压缩逻辑,捕获并打印异常信息,避免程序崩溃。 - 空值安全:判断
compressedImage不为空后再处理,消除强制解包导致的崩溃风险。
内容的提问来源于stack exchange,提问作者CodeSagePath
相关产品推荐
相关产品推荐

