choose_image_handler.dart 4.84 KB
import 'dart:io';

import 'package:appframe/services/dispatcher.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:image_picker/image_picker.dart';
import 'package:image_size_getter/file_input.dart';
import 'package:image_size_getter/image_size_getter.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';

class ChooseImageHandler implements MessageHandler {
  @override
  Future<dynamic> handleMessage(dynamic params) async {
    if (params is! Map<String, dynamic>) {
      throw Exception('参数错误');
    }
    var sourceType = params['sourceType'] as String;
    if (sourceType != 'album' && sourceType != 'camera') {
      throw Exception('参数错误');
    }
    // 暂时忽略对此参数的处理
    var sizeType = params['sizeType'] as List<dynamic>;
    if (sizeType.isEmpty || sizeType.length > 2) {
      throw Exception('参数错误');
    }
    var count = params['count'] as int;
    if (count < 1 || count > 9) {
      throw Exception('参数错误');
    }

    // 从相册选择
    if (sourceType == 'album') {
      if (count == 1) {
        return await _selectSingle();
      } else {
        return await _selectMulti(count);
      }
    }
    // 拍照
    else {
      return await _cameraSingle();
    }
  }

  ///
  /// 选择单张图片
  ///
  /// 将选择的图片放到应用的临时目录中,并在路径前面添加“/temp”,返回给调用方后,调用方可通过http方式访问图片
  ///
  Future<List<Map<String, dynamic>>?> _selectSingle() async {
    final ImagePicker picker = ImagePicker();

    final XFile? pickedFile = await picker.pickImage(source: ImageSource.gallery);

    // 用户取消选择,返回空数组
    if (pickedFile == null) {
      return [];
    }

    // 获取临时目录
    final Directory tempDir = await getTemporaryDirectory();

    return [await _handleOne(pickedFile, tempDir)];
  }

  ///
  /// 选择多张图片
  ///
  /// 将选择的图片放到应用的临时目录中,并在每个文件路径前面添加“/temp”,返回给调用方后,调用方可通过http方式访问图片
  ///
  Future<List<Map<String, dynamic>>?> _selectMulti(int limit) async {
    final ImagePicker picker = ImagePicker();

    final List<XFile> pickedFileList = await picker.pickMultiImage(limit: limit);

    // 用户取消选择,返回空数组
    if (pickedFileList.isEmpty) {
      return [];
    }

    // 限制最多limit张
    if(pickedFileList.length > limit) {
      pickedFileList.removeRange(limit, pickedFileList.length);
    }

    // 获取临时目录
    final Directory tempDir = await getTemporaryDirectory();

    final List<Map<String, dynamic>> result = [];
    for (final XFile? file in pickedFileList) {
      if (file != null) {
        result.add(await _handleOne(file, tempDir));
      }
    }

    return result;
  }

  ///
  /// 拍照
  ///
  Future<List<Map<String, dynamic>>?> _cameraSingle() async {
    final ImagePicker picker = ImagePicker();

    final XFile? pickedFile = await picker.pickImage(source: ImageSource.camera);

    // 用户取消选择,返回空数组
    if (pickedFile == null) {
      return [];
    }

    // 获取临时目录
    final Directory tempDir = await getTemporaryDirectory();

    return [await _handleOne(pickedFile, tempDir)];
  }

  Future<Map<String, dynamic>> _handleOne(XFile pickedFile, Directory tempDir) async {
    // 生成唯一文件名
    final String fileName = path.basename(pickedFile.path);
    final String uniqueFileName = '${DateTime.now().millisecondsSinceEpoch}_$fileName';

    // 创建目标文件路径
    final String tempFilePath = path.join(tempDir.path, uniqueFileName);

    // 复制文件到临时目录
    var sourceFile = File(pickedFile.path);
    final File copiedFile = await sourceFile.copy(tempFilePath);

    // 通过image_size_getter获取图片尺寸
    final sizeResult = ImageSizeGetter.getSizeResult(FileInput(sourceFile));
    final thumbnailPath = await _genThumbnail(sourceFile, tempDir);

    // 返回一个元素的数组
    return {
      "tempFilePath": "/temp${copiedFile.path}",
      "size": copiedFile.lengthSync(),
      "width": sizeResult.size.width,
      "height": sizeResult.size.height,
      "thumbTempFilePath": thumbnailPath,
      "fileType": copiedFile.path.split('/').last.split('.').last,
    };
  }

  Future<String?> _genThumbnail(File imageFile, Directory tempDir) async {
    try {
      // 缩略图路径
      final tempPath = tempDir.path;
      final targetPath = '$tempPath/thumbnail_${DateTime.now().millisecondsSinceEpoch}.jpg';

      // 压缩生成缩略图文件
      final compressedFile = await FlutterImageCompress.compressAndGetFile(imageFile.absolute.path, targetPath);

      return compressedFile!.path;
    } catch (e) {
      print('生成缩略图出错: $e');
      return null;
    }
  }
}