PAYATHON 2026

Flutter 如何在 Android 和 Linux 上正确保存 QR PNG?

数据阿明

结论

保存 PNG 时,直接使用 ui.Image.toByteData(format: ui.ImageByteFormat.png) 返回的字节。不要先把 PNG 字节转换成字符串,再用 utf8.encode 编码。这样会改变文件内容,可能导致图片无法正常打开。

这里的 pngBytes 是 PNG 二进制数据。原代码先将其转换成字符串,再把编码后的内容作为文件字节传入:

bytes: utf8.encode(String.fromCharCodes(uInt8List!)),

这种转换会改变原始二进制内容。

保存 PNG 字节

RenderRepaintBoundary 转换得到的 Uint8List 可以直接写入文件。提问者给出的方案分别处理 Android 和 Linux:在 Android 上,将字节传给 FilePicker.platform.saveFile;在 Linux 上,先获取保存路径,再用 File.writeAsBytes 写入文件。

Future<void> saveQrAsPng(Uint8List uInt8List) async {
  if (Platform.isAndroid) {
    await FilePicker.platform.saveFile(
      dialogTitle: 'Save File:',
      fileName: 'Store.png',
      bytes: uInt8List,
    );
  } else if (Platform.isLinux) {
    final outputFilePath = await FilePicker.platform.saveFile(
      dialogTitle: 'Save File:',
      fileName: 'Store.png',
    );

    if (outputFilePath != null) {
      final file = await File(outputFilePath).create();
      await file.writeAsBytes(uInt8List, flush: true);
    }
  }
}

捕获图片时,先检查 byteData 是否为空,再传递字节:

final byteData = await image.toByteData(
  format: ui.ImageByteFormat.png,
);

if (byteData == null) {
  return;
}

final pngBytes = byteData.buffer.asUint8List();
await vm.saveQrAsPng(pngBytes);

注意事项

saveFile 返回的路径可能为空,表示没有可用的输出路径,或者用户取消了操作。写入文件前应先检查返回值。提问者报告的测试环境是 Linux Mint 和 Android 14;其他平台或系统版本需要在实际环境中验证。

备注:内容仅供参考。