import 'dart:io'; import 'dart:ui'; import 'package:electronic_assistant/utils/pair.dart'; import 'package:electronic_assistant/utils/toast_util.dart'; import 'package:get/get.dart'; import 'package:just_audio/just_audio.dart'; import 'package:uuid/uuid.dart'; import '../data/bean/talks.dart'; import '../data/repositories/talk_repository.dart'; import '../dialog/loading_dialog.dart'; import '../module/talk/view.dart'; import '../resource/string.gen.dart'; import 'audio_picker_utils.dart'; import 'package:path_provider/path_provider.dart'; import 'common_utils.dart'; import 'error_handler.dart'; class FileUploadCheckHelper { FileUploadCheckHelper._(); static bool isAllowAudioFile(String path) { try { String ext = path.split('.').last; return AudioPickerUtils.allowFileType.contains(ext); } catch (e) { return false; } } static Future choicePlatformLocalFileAndCreateOrder( {VoidCallback? choiceSuccessCallback}) async { TalkBean? bean; try { Pair? pair = await FileUploadCheckHelper.pickerPlatformFile(); if (pair == null) { //未选择文件 return; } LoadingDialog.show(StringName.fileImporting.tr); bean = await FileUploadCheckHelper.createTalkFromLocalFile( pair.first, pair.second); choiceSuccessCallback?.call(); TalkPage.start(bean); } catch (e) { if (e is PickerException) { ToastUtil.showToast(e.message); } else { ErrorHandler.toastError(e, message: StringName.fileImportFail.tr); } } finally { LoadingDialog.hide(); } } static Future checkCanUpload(File file) async { //文件不能超过500M if (file.lengthSync() > 500 * 1024 * 1024) { throw PickerException(StringName.fileChoiceSizeLimit.tr); } AudioPlayer? player; try { player = AudioPlayer(); player.setAudioSource(AudioSource.uri(file.uri)); Duration? duration = await player.durationStream .firstWhere((duration) => duration != null); if (duration == null) { throw PickerException(StringName.fileAudioDurationCannotObtained.tr); } if (duration.inSeconds < 3) { throw PickerException(StringName.recordingDurationCannotLessThan3s.tr); } //录音时长不能超过5小时 if (duration.inHours > 5) { throw PickerException(StringName.fileAudioDurationLimit.tr); } return duration; } finally { player?.dispose(); } } static Future?> pickerPlatformFile() async { File? file = await AudioPickerUtils.pickSingleFileByPlatform(); if (file == null) { return null; } Duration duration = await checkCanUpload(file); return Pair(file, duration); } static Future createTalkFromLocalFile( File file, Duration duration) async { TalkBean bean = await talkRepository.talkCreate( const Uuid().v4(), duration.inSeconds, uploadType: FileUploadType.local); String childDirName = bean.id; Directory dir = await getChoiceUploadDir(childDirName); await moveFileToDirectory(file, dir); return bean; } static Future getChoiceUploadDir(String talkId) async { Directory documentDir = await getApplicationDocumentsDirectory(); return Directory("${documentDir.path}/.atmob/choice/$talkId"); } static Future getChoiceUploadFile(String talkId) async { Directory dir = await getChoiceUploadDir(talkId); if (!dir.existsSync()) { return null; } List list = dir.listSync(); if (list.isEmpty) { return null; } return list.first as File; } static Future moveFileToDirectory(File file, Directory dir) async { if (!dir.existsSync()) { dir.createSync(recursive: true); } String newFilePath = '${dir.path}/${file.uri.pathSegments.last}'; file.renameSync(newFilePath); } static const String _uploadServerAudioTag = '_&&@@##_'; //拼接设备ID用于标识 static String joinUploadServerAudioTag(String id) { return '${getDeviceId()}$_uploadServerAudioTag$id'; } static String? getLocalAudioId(String? tag) { if (tag == null || tag.isEmpty) { return null; } if (!tag.contains(_uploadServerAudioTag)) { return null; } List audioTag = tag.split(_uploadServerAudioTag); if (audioTag.first != getDeviceId()) { return null; } return tag.split(_uploadServerAudioTag).last; } } class PickerException implements Exception { final String message; PickerException(this.message); @override String toString() { return 'PickerException: $message'; } }