📜  在Flutter使用Dart在 MongoDB 上上传和检索图像

📅  最后修改于: 2021-09-02 05:43:53             🧑  作者: Mango

将文件从本地系统上传到专用服务器称为文件上传,从专用服务器向本地系统检索文件称为文件检索。它的工作原理与我们从 Android 设备中选择文件并单击提交按钮时的定义完全相同,Android 设备从本地存储中获取文件并借助 Http 请求将其发送到服务器,然后服务器执行它的工作是将文件保存到定义的位置。在本文中,我们将演示如何在flutter_image_compress插件的帮助下将图像文件存储和检索到 MongoDB Atlas 集群数据库中,同时将图像的大小从兆字节 (MB) 压缩到千字节 (KB)。

先决条件:要开始此操作,个人需要熟悉以下内容

  • Flutter
  • Dart
  • MongoDB
  • 蒙戈Dart

在这里,我们正在创建一个 Android 应用程序来演示 MongoDB 在Flutter应用程序中的使用。首先,我们需要安装某些Flutter包和插件,并且必须在本地系统中安装 Android Studio。

在开始之前,必须安装本地系统中的Flutter开发工具包和Android Studio IDE 中的Flutter插件。

  • 打开Android Studio并创建了一个名为“geeksforgeeks的名字一个新的flutter应用程序项目。
  • 创建项目并成功同步后,将您的 Android 设备连接到 Android Studio,并确保开发人员选项和 USB 调试处于开启状态。
  • 通过单击中心顶部的第一个绿色图标来运行项目以交叉检查项目是否已构建并成功运行(第一次 Android Studio 像往常一样需要多一点时间)。
  • 现在,是时候安装必要的包和插件了,从geeksforgeeks -> pubspec.yaml项目结构中打开‘pubspec.yaml’文件并复制粘贴三个依赖项,即 image_picker、flutter_image_compress 和 mongo_dart,如下所示。
dependencies:
  image_picker: ^0.6.7+7
  flutter_image_compress: ^0.7.0
  mongo_dart:
    git:
      url: https://github.com/mongo-dart/mongo_dart.git
  • 一旦完成上述步骤,然后单击出现在中心顶部的Packages get” flutter命令以安装所有必要的包和插件。

要上传和检索利用flutterDart让我们开始对MongoDB的图像,请按照每一个低于一个每一步。

步骤1:

由于整个应用程序构建在 Android 智能手机的顶部,因此无法与本地 MongoDB 数据库连接,这就是为什么在这里,我们将使用MongoDB 集群数据库,并与集群数据库连接所有我们需要的副本’ URI。

  • 注册或登录到 MongoDB 帐户并使用任何自定义名称创建一个数据库。
  • 要从 Atlas 获取这些副本,请转到“连接”->“与 Shell 连接”->“我安装了 Mongo Shell”->将您的版本设置为 3.4 或更早版本。
  • 如果您有 3 个副本,您将有 3 个 URL,用逗号分隔,如下所示。
Dart
final url = [
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority",
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority",
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority"
];


Dart
Future connection () async{
    Db _db = new Db.pool(url);
    await _db.open(secure: true);
    GridFS bucket = GridFS(_db,"image");
}


Dart
final pickedFile = await picker.getImage(source: ImageSource.gallery);
if(pickedFile!=null){
    var _cmpressed_image;
    try {
      _cmpressed_image = await FlutterImageCompress.compressWithFile(
          pickedFile.path,
          format: CompressFormat.heic,
          quality: 70
      );
     } catch (e) {
      _cmpressed_image = await FlutterImageCompress.compressWithFile(
          pickedFile.path,
          format: CompressFormat.jpeg,
          quality: 70
      );
     }
}


Dart
Map image = {
      "_id" : pickedFile.path.split("/").last,
      "data": base64Encode(_cmpressed_image)
};
  
var res = await bucket.chunks.insert(image);
var img = await bucket.chunks.findOne({
      "_id": pickedFile.path.split("/").last
});


Dart
import 'dart:convert';
import 'dart:io';
  
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:mongo_dart/mongo_dart.dart' show Db, GridFS;
  
void main() => runApp(MyApp());
  
class MyApp extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Geeks Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(title: 'GeeksforGeeks'),
    );
  }
}
  
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  
  
  final String title;
  
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
  
class _MyHomePageState extends State with SingleTickerProviderStateMixin{
  
  final url = [
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority",
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority",
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority"
  ];
  
  final picker = ImagePicker();
  File _image;
  GridFS bucket;
  AnimationController _animationController;
  Animation _colorTween;
  ImageProvider provider;
  var flag = false;
    
  @override
  void initState() {
  
    _animationController = AnimationController(
      duration: Duration(milliseconds: 1800),
      vsync: this,
    );
    _colorTween = _animationController.drive(ColorTween(begin: Colors.green, end: Colors.deepOrange));
    _animationController.repeat();
    super.initState();
    connection();
  }
  
  Future getImage() async{
    
    final pickedFile = await picker.getImage(source: ImageSource.gallery);
  
    if(pickedFile!=null){
  
      var _cmpressed_image;
      try {
        _cmpressed_image = await FlutterImageCompress.compressWithFile(
            pickedFile.path,
            format: CompressFormat.heic,
            quality: 70
        );
      } catch (e) {
  
        _cmpressed_image = await FlutterImageCompress.compressWithFile(
            pickedFile.path,
            format: CompressFormat.jpeg,
            quality: 70
        );
      }
      setState(() {
        flag = true;
      });
  
      Map image = {
        "_id" : pickedFile.path.split("/").last,
        "data": base64Encode(_cmpressed_image)
      };
      var res = await bucket.chunks.insert(image);
      var img = await bucket.chunks.findOne({
        "_id": pickedFile.path.split("/").last
      });
      setState(() {
        provider = MemoryImage(base64Decode(img["data"]));
        flag = false;
      });
    }
  }
    
  @override
  Widget build(BuildContext context) {
  
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        backgroundColor: Colors.green,
      ),
      body: SingleChildScrollView(
        child: Center(
          child:  Column(
            children: [
              SizedBox(
                height: 20,
              ),
              provider == null ? Text('No image selected.') : Image(image: provider,),
              SizedBox(height: 10,),
              if(flag==true)
                CircularProgressIndicator(valueColor: _colorTween),
              SizedBox(height: 20,),
              RaisedButton(
                onPressed: getImage,
                textColor: Colors.white,
                padding: const EdgeInsets.all(0.0),
                child: Container(
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      colors: [
                        Colors.green,
                        Colors.green[200],
                        Colors.green[900],
                      ],
                    ),
                  ),
                  padding: const EdgeInsets.all(10.0),
                  child: const Text(
                      'Select Image',
                      style: TextStyle(fontSize: 20)
                  ),
                ),
  
              ),
            ],
          ),
        )
      )
  
    );
  }
  
  Future connection () async{
    Db _db = new Db.pool(url);
    await _db.open(secure: true);
    bucket = GridFS(_db,"image");
  }
}


第2步:

首先是数据库连接,由于 Atlas 现在只允许 SSL 连接,我们将需要来自 TLS/SSL 的源来打开安全连接。对于Db.pool() 指令,我们必须传入以mongodb://开头的每个 URL,然后是/test?authSource=[auth db (probably ‘admin’)]我们可以看到一个副本示例上一步中的 URI。

Dart

Future connection () async{
    Db _db = new Db.pool(url);
    await _db.open(secure: true);
    GridFS bucket = GridFS(_db,"image");
}

第 3 步:

一旦我们建立了到 MongoDB 集群数据库的连接,我们现在可以开始定义我们的后端逻辑。由于上传和检索长尺寸图像非常耗时,有时会导致一系列问题,例如获取更多空间、成本更高、访问时间更多、数据过载更多,因此在此,我们压缩尺寸的步骤从MBKB保持纵横比的图像。

Dart

final pickedFile = await picker.getImage(source: ImageSource.gallery);
if(pickedFile!=null){
    var _cmpressed_image;
    try {
      _cmpressed_image = await FlutterImageCompress.compressWithFile(
          pickedFile.path,
          format: CompressFormat.heic,
          quality: 70
      );
     } catch (e) {
      _cmpressed_image = await FlutterImageCompress.compressWithFile(
          pickedFile.path,
          format: CompressFormat.jpeg,
          quality: 70
      );
     }
}

第四步:

现在,这是这里的第四步也是最后一步,我们将构建查询以将图像上传和检索到 MongoDB,因此,集群数据库。由于 MongoDB 支持类似JSON 的(即键值对)数据格式,因此我们必须创建一个具有两个键值对的 Hashmap,分别是“ _id”“data”,以分别存储图像唯一 id 和图像像素数据。

Dart

Map image = {
      "_id" : pickedFile.path.split("/").last,
      "data": base64Encode(_cmpressed_image)
};
  
var res = await bucket.chunks.insert(image);
var img = await bucket.chunks.findOne({
      "_id": pickedFile.path.split("/").last
});

现在,是时候展示完整的方法了,打开‘main。 dart’文件来自geeksforgeeks -> lib -> main。 dart项目目录结构并复制粘贴整个代码。

Dart

import 'dart:convert';
import 'dart:io';
  
import 'package:flutter/material.dart';
import 'package:image_picker/image_picker.dart';
import 'package:flutter_image_compress/flutter_image_compress.dart';
import 'package:mongo_dart/mongo_dart.dart' show Db, GridFS;
  
void main() => runApp(MyApp());
  
class MyApp extends StatelessWidget {
  
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Geeks Demo',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        primarySwatch: Colors.green,
      ),
      home: MyHomePage(title: 'GeeksforGeeks'),
    );
  }
}
  
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
  
  
  final String title;
  
  @override
  _MyHomePageState createState() => _MyHomePageState();
}
  
class _MyHomePageState extends State with SingleTickerProviderStateMixin{
  
  final url = [
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority",
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority",
      "mongodb://:@:27017/?ssl=true&
      replicaSet=&authSource=admin&retryWrites=true&w=majority"
  ];
  
  final picker = ImagePicker();
  File _image;
  GridFS bucket;
  AnimationController _animationController;
  Animation _colorTween;
  ImageProvider provider;
  var flag = false;
    
  @override
  void initState() {
  
    _animationController = AnimationController(
      duration: Duration(milliseconds: 1800),
      vsync: this,
    );
    _colorTween = _animationController.drive(ColorTween(begin: Colors.green, end: Colors.deepOrange));
    _animationController.repeat();
    super.initState();
    connection();
  }
  
  Future getImage() async{
    
    final pickedFile = await picker.getImage(source: ImageSource.gallery);
  
    if(pickedFile!=null){
  
      var _cmpressed_image;
      try {
        _cmpressed_image = await FlutterImageCompress.compressWithFile(
            pickedFile.path,
            format: CompressFormat.heic,
            quality: 70
        );
      } catch (e) {
  
        _cmpressed_image = await FlutterImageCompress.compressWithFile(
            pickedFile.path,
            format: CompressFormat.jpeg,
            quality: 70
        );
      }
      setState(() {
        flag = true;
      });
  
      Map image = {
        "_id" : pickedFile.path.split("/").last,
        "data": base64Encode(_cmpressed_image)
      };
      var res = await bucket.chunks.insert(image);
      var img = await bucket.chunks.findOne({
        "_id": pickedFile.path.split("/").last
      });
      setState(() {
        provider = MemoryImage(base64Decode(img["data"]));
        flag = false;
      });
    }
  }
    
  @override
  Widget build(BuildContext context) {
  
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        backgroundColor: Colors.green,
      ),
      body: SingleChildScrollView(
        child: Center(
          child:  Column(
            children: [
              SizedBox(
                height: 20,
              ),
              provider == null ? Text('No image selected.') : Image(image: provider,),
              SizedBox(height: 10,),
              if(flag==true)
                CircularProgressIndicator(valueColor: _colorTween),
              SizedBox(height: 20,),
              RaisedButton(
                onPressed: getImage,
                textColor: Colors.white,
                padding: const EdgeInsets.all(0.0),
                child: Container(
                  decoration: BoxDecoration(
                    gradient: LinearGradient(
                      colors: [
                        Colors.green,
                        Colors.green[200],
                        Colors.green[900],
                      ],
                    ),
                  ),
                  padding: const EdgeInsets.all(10.0),
                  child: const Text(
                      'Select Image',
                      style: TextStyle(fontSize: 20)
                  ),
                ),
  
              ),
            ],
          ),
        )
      )
  
    );
  }
  
  Future connection () async{
    Db _db = new Db.pool(url);
    await _db.open(secure: true);
    bucket = GridFS(_db,"image");
  }
}

最后,通过单击中间顶部的第一个绿色图标来运行项目以查看输出,您的工作就完成了。

输出:

访问图像