如何将资产列表编码为 base64 并在颤振中对其进行解码?

时间:2021-07-06 09:17:36

标签: flutter base64 decode assets encode

在我的应用中,用户可以从图库中选择多个图像,这些图像被保存为资产列表,并将它们显示在屏幕上。这一切都发生在有状态的小部件中,我想对当前选择的图像进行编码并将编码的资产保存在列表中,然后能够对其进行解码。

我用于编码和解码名为 images 的资产列表的代码:

 
  if (image_list.length > 0) {
    for (var i = 0; i < image_list.length; i++) {
      final byteData = await image_list[i].getByteData();
      final tempFile =
          File("${(await getTemporaryDirectory()).path}/${image_list[i].name}");
      final file = await tempFile.writeAsBytes(
        byteData.buffer
            .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes),
      );
      final bytes = await file.readAsBytes();
      String base64Encode(List<int> bytes) => base64.encode(bytes);
      String encoded_image = base64Encode(bytes);
      image_list_encoded.add(encoded_image);
    }
  }
  return image_list_encoded;
}

Future<List<Image>> decodeImages(List<String> image_list_encoded) async {
  if (new_image_list_encoded.length > 0) {
    for (var i = 0; i < new_image_list_encoded.length; i++) {
      final decodedBytes = base64Decode(new_image_list_encoded[i]);
      var decoded_file = Image.memory(decodedBytes);
      image_list_decoded.add(decoded_file);
    }
  }
  return image_list_decoded;
}

单击检查按钮后,我尝试检查编码图像是否正确编码:

IconButton(
            icon: Icon(
              Icons.check,
              color: Colors.white,
            ),
            onPressed: () async {
              final form = _formKey.currentState;
              if (form!.validate()) {
                form.save();
              }
              var encoded_images = await encodeImages(images);
              print(savedProjectName);
              print(savedProjectDescription);
              print(encoded_images);
            },
          ),

问题是,当我打印编码后的字符串时,无论选择哪张图片,打印的编码字符串都是一样的;不幸的是,我现在无法提供这个字符串,因为现在,由于 path_provider 插件不再工作,整个程序不再工作。我怀疑这是问题所在,因为一旦我安装插件并在程序中使用它,我就会收到此错误:

Error: Cannot run with sound null safety, because the following dependencies
don't support null safety:

- package:plugin_platform_interface

For solutions, see https://dart.dev/go/unsound-null-safety

Unhandled exception:
Bad state: Unsupported Null Safety mode NonNullableByDefaultCompiledMode.Invalid, in null.
#0      ProgramCompiler.emitModule (package:dev_compiler/src/kernel/compiler.dart:439:9)
#1      JavaScriptBundler.compile (package:frontend_server/src/javascript_bundle.dart:146:33)
#2      FrontendCompiler.writeJavascriptBundle (package:frontend_server/frontend_server.dart:638:47)
<asynchronous suspension>

#3      FrontendCompiler.compile (package:frontend_server/frontend_server.dart:549:9)
<asynchronous suspension>
#4      listenAndCompile.<anonymous closure> (package:frontend_server/frontend_server.dart:1119:11)
<asynchronous suspension>

the Dart compiler exited unexpectedly.
Exited (sigterm)
Failed to compile application.

但是,如果没有这个插件,我的编码函数中的函数 getTemporaryDirectory() 没有定义。您是否知道一种不同的方式来编码和解码这些资产,然后能够在以后打印编码版本?

完整代码:

ProjectDescriptionField savedDescription = ProjectDescriptionField();
ProjectNameField savedName = ProjectNameField();
AddPage savedPage = AddPage();
_AddPageState savedPageState = _AddPageState();
List<String> image_list_encoded = [];
final _formKey = GlobalKey<FormState>();
final projectNameController = TextEditingController();
final projectDescriptionController = TextEditingController();
String? savedProjectName = '';
String? savedProjectDescription = '';
List<Image> image_list_decoded = [];
List<Asset> asset_list_decoded = [];
List<String> new_image_list_encoded = image_list_encoded;

class AddPage extends StatefulWidget {
  final _AddPageState _addPageState = _AddPageState();
  AddPage({Key? key}) : super(key: key);

  @override
  _AddPageState createState() => _AddPageState();
  //return _addPageState;
}

class _AddPageState extends State<AddPage> {
  List<Asset> images = <Asset>[];
  String _error = NOERROR;
  @override
  Widget build(BuildContext context) {
    if (images.isEmpty)
      return AppLayout(logicalHeight * 0.15);
    else
      return AppLayout(logicalHeight * 0.01);
  }

  Future<void> loadAssets() async {
    List<Asset> resultList = <Asset>[];
    String error = NOERROR;

    try {
      resultList = await MultiImagePicker.pickImages(
        maxImages: 300,
        enableCamera: true,
        selectedAssets: images,
        cupertinoOptions: CupertinoOptions(takePhotoIcon: "chat"),
        materialOptions: MaterialOptions(
          actionBarColor: "#abcdef",
          actionBarTitle: "Example App",
          allViewTitle: "All Photos",
          useDetailsView: false,
          selectCircleStrokeColor: "#000000",
        ),
      );
    } on Exception catch (e) {
      error = e.toString();
    }

    if (!mounted) return;

    setState(() {
      images = resultList;
      _error = error;
    });
  }

  List<Asset> getImages() {
    return images;
  }

  Widget AppLayout(double distanceFromImages) {
    return Scaffold(
      appBar: AppBar(
        leading: BackButton(color: Colors.white),
        title: Text(CREATEPROJECT),
        actions: <Widget>[
          IconButton(
            icon: Icon(
              Icons.check,
              color: Colors.white,
            ),
            onPressed: () async {
              final form = _formKey.currentState;
              if (form!.validate()) {
                form.save();
              }
              var encoded_images = await encodeImages(images);
              var decoded_images = decodeImages(encoded_images);
              print(savedProjectName);
              print(savedProjectDescription);
              print(encoded_images);
            },
          ),
        ],
      ),
      body: Form(
          key: _formKey,
          child: Column(children: <Widget>[
            Padding(
              padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.02, 0, 0),
              child: Center(
                  child: Container(
                height: logicalHeight * 0.05,
                width: logicalWidth * 0.9,
                child: TextFormField(
                    controller: projectNameController,
                    decoration: InputDecoration(
                        hintText: PROJECTNAME, border: UnderlineInputBorder()),
                    maxLength: 30,
                    validator: (value) {
                      if (value!.isEmpty) {
                        return 'This is a required field';
                      }
                      return null;
                    },
                    onSaved: (value) => savedProjectName = value),
              )),
            ),
            Padding(
                padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
                child: ElevatedButton(
                  child: Text(PICKIMAGES),
                  onPressed: loadAssets,
                )),
            Center(
                child: Padding(
                    padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.01, 0, 0),
                    child: getWidget())),
            Padding(
              padding: EdgeInsets.fromLTRB(logicalWidth * 0.05,
                  distanceFromImages, logicalWidth * 0.05, 0),
              child: Center(
                  child: Container(
                      // child: savedDescription
                      child: TextFormField(
                          controller: projectDescriptionController,
                          decoration: InputDecoration(
                              hintText: PROJECTDESCRIPTION,
                              border: UnderlineInputBorder()),
                          maxLines: 5,
                          minLines: 1,
                          maxLength: 5000,
                          validator: (value) {
                            if (value!.isEmpty) {
                              return 'This is a required field';
                            }
                            return null;
                          },
                          onSaved: (value) =>
                              savedProjectDescription = value))),
            ),
          ])),
    );
  }

  Widget getWidget() {
    if (images.length > 0) {
      //Would it be better to make a list of all items in images using List.generate so that we avoid this if statement
      return Container(
          height: logicalHeight * 0.4,
          width: logicalWidth * 0.8,
          child: ImagePages());
    } else {
      return Padding(
          padding: EdgeInsets.fromLTRB(0, logicalHeight * 0.15, 0, 0),
          child: Container(child: Text(NOPICTURESSELECTED)));
    }
  }

  PageView ImagePages() {
    final PageController controller = PageController(initialPage: 0);
    List<Widget> children = [];
    images.forEach((element) {
      children.add(Padding(
          padding: EdgeInsets.fromLTRB(
              logicalWidth * 0.01, 0, logicalWidth * 0.01, 0),
          child: AssetThumb(
            asset: element,
            width: 1000,
            height: 1000,
          )));
    });
    return PageView(
      scrollDirection: Axis.horizontal,
      controller: controller,
      children: children,
    );
  }
}

Future<List<String>> encodeImages(List<Asset> image_list) async {
  //use savedPage._addPageState.getImages() as image_list
  if (image_list.length > 0) {
    for (var i = 0; i < image_list.length; i++) {
      final byteData = await image_list[i].getByteData();
      final tempFile =
          File("${(await getTemporaryDirectory()).path}/${image_list[i].name}");
      final file = await tempFile.writeAsBytes(
        byteData.buffer
            .asUint8List(byteData.offsetInBytes, byteData.lengthInBytes),
      );
      final bytes = await file.readAsBytes();
      String base64Encode(List<int> bytes) => base64.encode(bytes);
      String encoded_image = base64Encode(bytes);
      image_list_encoded.add(encoded_image);
    }
  }
  return image_list_encoded;
}

Future<List<Image>> decodeImages(List<String> image_list_encoded) async {
  if (new_image_list_encoded.length > 0) {
    for (var i = 0; i < new_image_list_encoded.length; i++) {
      final decodedBytes = base64Decode(new_image_list_encoded[i]);
      var decoded_file = Image.memory(decodedBytes);
      image_list_decoded.add(decoded_file);
    }
  }
  return image_list_decoded;
}

void saveNewProject(SavedData savedData) {
  //TODO save the data to FireBase
  //save data includes:
  //  project name
  //  project description
  //  list of assets
}

class ProjectNameField extends StatefulWidget {
  ProjectNameFieldState _nameFieldState = ProjectNameFieldState();
  @override
  ProjectNameFieldState createState() {
    return ProjectNameFieldState();
    //return _nameFieldState;
  }
}

class ProjectNameFieldState extends State<ProjectNameField> {
  final myController = TextEditingController();
  //how do you read out the information from that textfield, it may have been better to use the previous method with userInput
  @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    myController.dispose();
    super.dispose();
  }

  Widget build(BuildContext context) {
    return TextField(
      controller: myController,
      decoration: InputDecoration(
        border: UnderlineInputBorder(),
        hintText: PROJECTNAME,
      ),
      maxLength: 30,
    );
  }
}

class ProjectDescriptionField extends StatefulWidget {
  ProjectDescriptionFieldState _descriptionFieldState =
      ProjectDescriptionFieldState();
  @override
  ProjectDescriptionFieldState createState() {
    return _descriptionFieldState;
    //return ProjectDescriptionFieldState();
  }
}

class ProjectDescriptionFieldState extends State<ProjectDescriptionField> {
  final myController = TextEditingController();

  @override
  void dispose() {
    // Clean up the controller when the widget is disposed.
    myController.dispose();
    super.dispose();
  }

  Widget build(BuildContext context) {
    return TextField(
      controller: myController,
      decoration: InputDecoration(
        border: UnderlineInputBorder(),
        hintText: PROJECTDESCRIPTION,
      ),
      minLines: 1,
      maxLines: 5,
      maxLength: 5000,
    );
  }
}

class SavedData {
  String saved_Project_Name = "";
  String saved_Project_Description = "";
  List<Asset> saved_images = [];

  SavedData(String saved_Project_Name, String saved_Project_Description,
      List<Asset> saved_images) {
    this.saved_Project_Name = saved_Project_Name;
    this.saved_Project_Description = saved_Project_Description;
    this.saved_images = saved_images;
  }
}

0 个答案:

没有答案