Flutter数据库交互插件couchdb的使用

插件couchdb概述

CouchDB 是一种完全拥抱 Web 的数据库系统。数据以 JSON 文档的形式存储,并通过 HTTP 访问。要使用此库,您需要对 CouchDB 有一定的了解。更多信息可以在官方文档站点找到。

API

与数据库的连接以及身份验证由 CouchDbClient 处理,适用于 Web 和服务器环境。

身份验证类型

有三种身份验证方式可用:

  • 基本认证
  • Cookie 认证
  • 代理认证
基本认证

只需在构造函数中传递 usernamepassword

final c = CouchDbClient(username: 'name', password: 'pass');
Cookie 认证

还需要提供 auth 参数,并调用 authenticate() 方法(默认情况下,Cookie 有效期为 10 分钟,可以指定其他过期时间在 Expiration 头部):

final c = CouchDbClient(username: 'name', password: 'pass', auth: 'cookie');
final res = await c.authenticate();
代理认证

对于代理认证,需要传递 username 并提供以下头部信息:

  • X-Auth-CouchDB-UserName: 用户名(默认使用构造函数传递的用户名,因此可以省略)
  • X-Auth-CouchDB-Roles: 用户角色的逗号分隔列表
  • X-Auth-CouchDB-Token: 认证令牌。如果启用了 proxy_use_secret(强烈建议!),则此头部提供了用于认证的用户名的 HMAC 和用于防止来自不可信来源请求的秘密令牌(默认使用构造函数传递的用户名和秘密,因此可以省略)

示例代码:

final c = CouchDbClient(username: 'name', auth: 'proxy', secret: '92de07df7e7a3fe14808cef90a7cc0d91');
c.modifyRequestHeaders(<String, String>{
  'X-Auth-CouchDB-Roles': 'users,blogger'
});

注意:如果未启用 proxy_use_secret,则无需提供 X-Auth-CouchDB-Token

配置文件示例:

[chttpd_auth]
proxy_use_secret = false

否则,您可以提供 secret 选项,该选项用于生成令牌。客户端和 CouchDB 节点上的密钥应相同:

[chttpd_auth]
secret = 92de07df7e7a3fe14808cef90a7cc0d91

要使用此认证方法,请确保 {chttpd_auth, proxy_authentication_handler} 值已添加到 chttpd/authentication_handlers 的活动列表中:

[chttpd]
authentication_handlers = {chttpd_auth, cookie_authentication_handler}, {chttpd_auth, proxy_authentication_handler}, {chttpd_auth, default_authentication_handler}

匿名用户

您可以配置您的数据库允许匿名用户访问。为此,您必须提供以下选项(并且不要在 CouchDbClient 构造函数中设置 usernamepassword):

[chttpd]
require_valid_user = false

否则,不允许任何匿名用户的请求。

客户端

如果您希望直接通过客户端的方法(如 get()post())与服务器通信,但其他类提供了抽象协议细节的功能。因此,通常不推荐直接使用客户端的方法。

大多数客户端方法返回一个 Future<ApiResponse> 对象。当未来完成时,它将包含:

  • ApiResponse.json 属性(Map 类型)包含 CouchDB 发送的 JSON
  • ApiResponse.raw 属性(String 类型)用于非 JSON 对象的响应(数字、列表、文件等)
  • ApiResponse.headers 属性包含 HTTP 响应的头信息

如果失败,异常负载 response 将是一个 ErrorResponse 对象。

由于响应信息量大,包已按类别组织,每个类别都提供更具体的 <...Response> 类。

更多详细信息请参阅包 API。

分类

API 分为五个类别或领域,每个类别代表数据库整体的不同方面。这五个类别是:

  1. 服务器
  2. 数据库
  3. 文档
  4. 设计文档
  5. 本地文档

1. 服务器

Server 类表示。此类别提供 CouchDB 的服务器级交互,例如管理复制或获取有关服务器的基本信息。还包括有关身份验证和当前用户的信息(CouchDbClient 类中的方法)。

Server 类的方法返回 Future<ServerResponse>

2. 数据库

CouchDB 中的一个数据库是位于给定数据库服务器上的单个文档存储。这部分 API 由 Databases 类表示。您使用此类别在数据库级别与您的数据交互;例如创建新数据库或执行查询以搜索某些文档。

Databases 类的方法返回 Future<DatabasesResponse>

3. 文档

您使用 Documents 类在文档级别与数据交互。这包括获取特定文档、添加新文档或将文件附加到文档等功能。请注意,此类别不建模文档本身,而是与它们的交互。文档本身表示为 Maps。

Documents 类的方法返回 Future<DocumentsResponse>

4. 设计文档

设计文档提供数据库中数据的视图。您通过 DesignDocuments 类与其交互。

DesignDocuments 类的方法返回 Future<DesignDocumentsResponse>

5. 本地文档

本地文档与普通文档没有区别,唯一的例外是在复制期间不会将其复制到 CouchDB 的其他实例中。您通过 LocalDocuments 类与其交互。

LocalDocuments 类的方法返回 Future<LocalDocumentsResponse>

CORS

跨域资源共享 (CORS) 是一种使 Web 应用能够与托管它的服务器以外的服务器通信的方法。仅当应用程序在浏览器中运行时才需要。

CouchDB 服务器配置

如果应用程序不在与 CouchDB 实例相同的源上(或您在服务器上使用不同的端口),则远程 CouchDB 必须配置以下选项:

[httpd]
enable_cors = true
[cors]
origins = *
credentials = true
methods = GET, PUT, POST, HEAD, DELETE, COPY
headers = accept, authorization, content-type, origin, referer, x-csrf-token

这些设置可以在 Fauxton 配置实用程序或 CouchDB 的 local.ini 文件中更改。为了更好的安全性,在 origins 部分指定特定域而不是 *

浏览器客户端配置

根据浏览器的不同,您可能还需要向 CouchDbClient 构造函数传递 cors=true。然而,大多数时候浏览器会为您处理此事,因此这不是必需的。实际上,这可能会在浏览器控制台中引发“不安全头”消息。

使用示例

示例 1:服务器

import 'package:couchdb/couchdb.dart';

Future<void> main() async {
  final client = CouchDbClient(username: 'name', password: 'password');
  final db = Databases(client);
  final doc = Documents(client);

  try {
    final DatabasesResponse response1 = await db.allDocs('some_db');

    for (var i in response1.rows) {
      // Some code here
    }

    final DocumentsResponse response2 = await doc.doc('another_db', 'some_id');

    var thing = response2.doc['some_attribute'];

  } on CouchDbException catch (e) {
    print('$e - error');
  }
}

示例 2:浏览器

import 'dart:html';

import 'package:couchdb/couchdb.dart';

Future<void> main(List<String> args) async {
  final ButtonElement btn = querySelector('#data');
  final DivElement output = querySelector('#output');

  final c = CouchDbClient(username: 'name', password: 'pass', cors: true);
  final dm = Documents(c);

  btn.onClick.listen((event) async {
    try {
      final DocumentsResponse response1 = await dm.doc('some_db', 'some_doc_id');

      final Map<String, Object> doc = response1.doc;

      // Some code here

      // There properties are extracted from [doc] in order to gets direct access
      final String id = response1.id;
      final String rev = response1.rev;
      final Object attachment = response1.attachment;

      // Another code here

    } on CouchDbException catch (e) {
        window.console.log('${e.code} - error');
      }
    });
}

更多关于Flutter数据库交互插件couchdb的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter数据库交互插件couchdb的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


在Flutter中使用CouchDB进行数据库交互,你可以使用couchdb插件。CouchDB是一个NoSQL数据库,它使用HTTP/JSON API进行数据交互。couchdb插件提供了一个简单的方式来与CouchDB进行交互。

1. 添加依赖

首先,你需要在pubspec.yaml文件中添加couchdb插件的依赖:

dependencies:
  flutter:
    sdk: flutter
  couchdb: ^1.0.0  # 请检查最新版本

然后运行flutter pub get来安装依赖。

2. 初始化CouchDB客户端

在你的Flutter应用中,你可以初始化一个CouchDB客户端来与CouchDB服务器进行交互。

import 'package:couchdb/couchdb.dart';

void main() async {
  final client = CouchDbClient(
    protocol: 'http',
    host: 'localhost',
    port: 5984,
    user: 'your_username',
    password: 'your_password',
  );

  // 测试连接
  try {
    final response = await client.serverInfo();
    print('Connected to CouchDB: ${response.jsonBody}');
  } catch (e) {
    print('Failed to connect to CouchDB: $e');
  }
}

3. 创建数据库

你可以使用CouchDB客户端来创建一个新的数据库。

void createDatabase(CouchDbClient client) async {
  try {
    final response = await client.createDb('my_database');
    print('Database created: ${response.jsonBody}');
  } catch (e) {
    print('Failed to create database: $e');
  }
}

4. 插入文档

你可以向数据库中插入文档。

void insertDocument(CouchDbClient client) async {
  final document = {
    '_id': '1',
    'name': 'John Doe',
    'age': 30,
  };

  try {
    final response = await client.insertDoc('my_database', document);
    print('Document inserted: ${response.jsonBody}');
  } catch (e) {
    print('Failed to insert document: $e');
  }
}

5. 查询文档

你可以从数据库中查询文档。

void getDocument(CouchDbClient client) async {
  try {
    final response = await client.getDoc('my_database', '1');
    print('Document retrieved: ${response.jsonBody}');
  } catch (e) {
    print('Failed to retrieve document: $e');
  }
}

6. 更新文档

你可以更新数据库中的文档。

void updateDocument(CouchDbClient client) async {
  final document = {
    '_id': '1',
    '_rev': '1-abc123',  // 需要提供文档的_rev值
    'name': 'John Doe',
    'age': 31,
  };

  try {
    final response = await client.insertDoc('my_database', document);
    print('Document updated: ${response.jsonBody}');
  } catch (e) {
    print('Failed to update document: $e');
  }
}

7. 删除文档

你可以从数据库中删除文档。

void deleteDocument(CouchDbClient client) async {
  try {
    final response = await client.deleteDoc('my_database', '1', '1-abc123');
    print('Document deleted: ${response.jsonBody}');
  } catch (e) {
    print('Failed to delete document: $e');
  }
}

8. 关闭连接

当你完成所有操作后,可以关闭CouchDB客户端。

void closeClient(CouchDbClient client) {
  client.close();
}

9. 完整示例

以下是一个完整的示例,展示了如何初始化CouchDB客户端、创建数据库、插入、查询、更新和删除文档。

import 'package:couchdb/couchdb.dart';

void main() async {
  final client = CouchDbClient(
    protocol: 'http',
    host: 'localhost',
    port: 5984,
    user: 'your_username',
    password: 'your_password',
  );

  try {
    // 测试连接
    final serverInfo = await client.serverInfo();
    print('Connected to CouchDB: ${serverInfo.jsonBody}');

    // 创建数据库
    await client.createDb('my_database');
    print('Database created');

    // 插入文档
    final document = {
      '_id': '1',
      'name': 'John Doe',
      'age': 30,
    };
    await client.insertDoc('my_database', document);
    print('Document inserted');

    // 查询文档
    final retrievedDoc = await client.getDoc('my_database', '1');
    print('Document retrieved: ${retrievedDoc.jsonBody}');

    // 更新文档
    final updatedDocument = {
      '_id': '1',
      '_rev': retrievedDoc.jsonBody['_rev'],
      'name': 'John Doe',
      'age': 31,
    };
    await client.insertDoc('my_database', updatedDocument);
    print('Document updated');

    // 删除文档
    await client.deleteDoc('my_database', '1', updatedDocument['_rev']);
    print('Document deleted');
  } catch (e) {
    print('Error: $e');
  } finally {
    // 关闭客户端
    client.close();
  }
}
回到顶部