我正在写一个dart 包(不是dart ).我已经将一些位图图像作为公共assets资源 ,例如lib/assets/empty.png.当此软件包作为最终用户的命令行应用程序运行时,如何获取用户系统上这些assets资源 的文件路径?

用例:我的Dart包调用FFMPEG,我需要告诉FFMPEG在使用我的包的系统上从哪里找到这些assets资源 文件.例如,对FFMPEG的调用可能如下所示:

ffmpeg -i "path/to/lib/assets/empty.png" ...

推荐答案

访问Dart包的assets资源 有两种方式:

  1. 使用dart工具运行Dart CLI应用程序并访问依赖项的assets资源 ,或
  2. 运行可执行CLI应用程序

这两种情况之间的区别在于,当您使用dart工具运行CLI应用程序时,您的所有依赖项都可以作为 struct 化包在系统的本地缓存中使用.然而,当您运行一个可执行文件时,所有相关的代码都被编译成一个二进制文件,这意味着您在运行时不再有权访问依赖项的包,您只能访问依赖项的摇动树的编译代码.

Accessing assets when running with dart

以下代码将包assets资源 URI解析为文件系统路径.

final packageUri = Uri.parse('package:your_package/your/asset/path/some_file.whatever');
final future = Isolate.resolvePackageUri(packageUri);

// waitFor is strongly discouraged in general, but it is accepted as the
// only reasonable way to load package assets outside of Flutter.
// ignore: deprecated_member_use
final absoluteUri = waitFor(future, timeout: const Duration(seconds: 5));

final file = File.fromUri(absoluteUri);
if (file.existsSync()) {
  return file.path;
}

此解析代码改编自Tim Sneath的winmd软件包:https://github.com/timsneath/winmd/blob/main/lib/src/metadatastore.dart#L84-L106

运行可执行文件时访问assets资源

将客户端应用程序编译为可执行文件时,该客户端应用程序无法访问与依赖包一起存储的任何assets资源 文件.然而,有一种变通方法可能对某些人有效(它对我有效).您可以在包中的Dart代码中存储assets资源 的Base64编码版本.

首先,将每个assets资源 编码为Base64字符串,并将这些字符串存储在Dart代码中的某个位置.

const myAsset = "iVBORw0KGgoAAA....kJggg==";

然后,在运行时,将字符串解码回字节,然后将这些字节写入本地文件系统上的新文件.以下是我在 case 中使用的方法:

/// Writes this asset to a new file on the host's file system.
///
/// The file is written to [destinationDirectory], or the current
/// working directory, if no destination is provided.
String inflateToLocalFile([Directory? destinationDirectory]) {
  final directory = destinationDirectory ?? Directory.current;   
  final file = File(directory.path + Platform.pathSeparator + fileName);

  file.createSync(recursive: true);
  final decodedBytes = base64Decode(base64encoded);
  file.writeAsBytesSync(decodedBytes);

  return file.path;
}

@passsy人建议采用这种方法

Dart相关问答推荐

如何防止 getter 或函数每次都重新计算?

在Flutter中在 initstate() 之前调用了dependOnInheritedElement()

如何在 Flutter 中向 AnimationController 添加 Curves 类动画?

VSCode Flutter Dart 启动慢的建议

dart:js 和 js 包有什么区别?

如何等待forEach完成异步回调?

在 Windows 10 中使用 Android Studio 时没有Remove Widget选项

多级异步代码中的 Dart 错误

找不到名为split-per-abi的选项

如何在Flutter中正确显示Snackbar?

Flutter中不能指定MultiPartFile的内容类型

使用元组解包样式交换两个变量的值

Expansion Panel底部溢出

'dart:async' 的函数 `runZoned` 的用途

如何在 Angular.Dart 中以编程方式添加组件?

何时使用polymer点击或点击?

Dart MD5 字符串

你如何命名一个 Dart 类?

Dart: 必须取消 Stream 订阅并关闭 StreamSinks 吗?

如何在 Dart 中连接两个字符串?