Flutter文件共享服务插件samba_server的使用

发布于 1周前 作者 songsunli 来自 Flutter

Flutter 文件共享服务插件 samba_server 的使用

快速开始

以下是一个简单的示例,展示了如何使用 samba_server 插件来创建一个简单的 HTTP 服务器,并处理一些基本请求。

import 'dart:async';

import 'package:samba_server/samba_server.dart';

// 定义一个简单的 GET 路由
class HelloRoute extends Route {
  HelloRoute() : super(HttpMethod.get, '/');

  @override
  FutureOr<Response> handler(Request request) {
    return Response.ok(body: 'Hello from SAMBA_SERVER');
  }
}

// 定义一个 WebSocket 路由
class ChatSocketRoute extends WebSocketRoute {
  @override
  FutureOr<void> onConnected(WebSocket webSocket) {
    // 当客户端连接时触发
    webSocket.emit('message', {'connectionStatus': 'successful'});
    
    // 监听来自客户端的消息
    webSocket.on('message', (data) {
      print('Received message: $data');
    });
  }
}

Future<void> main() async {
  final httpServer = HttpServer();
  
  // 注册路由
  httpServer
    ..registerRoute(HelloRoute())
    ..registerRoute(ChatSocketRoute());
  
  // 绑定服务器地址和端口
  await httpServer.bind(address: '127.0.0.1', port: 8080);
}

特性

  • 高性能: samba_server 是一个为 API 和事件驱动的 WebSocket 开发而设计的高效后端开发框架。
  • 基于 Radix Trie 的健壮路由系统
  • 支持事件驱动的 WebSocket 与房间功能
  • 可以拦截任何请求或响应进行预处理或后处理
  • 优雅的错误处理
  • 高覆盖率的测试

安装

  1. 确保已经安装了 Dart SDK 3.0.0 或更高版本。
  2. 使用 dart pub add samba_server 命令将 samba_server 添加到你的项目中。

运行测试

为了运行测试套件,首先需要安装依赖项,然后运行测试套件。注意 -j 1 是必需的参数,以防止所有测试并行运行导致某些测试失败。

dart pub get
dart test -j 1

作者

Samba Server 的原始作者和主要维护者是 @tejHackerDev

请求

请求类是 HttpRequest 类的一个包装器,包含有关传入服务器请求的信息。

路径参数

路径参数是一个 Map<String, String>,其中键是动态路径参数的名称,值是在运行时传递的值。

查询参数

查询参数是一个 Map<String, dynamic>,其中键是请求中传递的名称,值是相应键传递的数据。

请求头

请求头是一个 Map<String, String>,其中键是头部名称,值是该名称传递的数据。如果为同一键传递多个值,则它们将用逗号连接。

请求体

请求体是一个 dynamic 类型,默认情况下如果没有传递请求体则为 null。如果传递了请求体,则默认类型为 Stream<Uint8List>,除非通过任何请求解码器转换。

请求解码器

请求解码器是一个自定义拦截器类,可以根据请求头中的 content-type 对请求体进行解码。默认情况下,Samba Server 提供了一些内置的请求解码器,例如 StringRequestDecoderFormUrlencodedRequestDecoderJsonRequestDecoderMultipartRequestDecoder

响应

响应类是 HttpResponse 类的一个包装器,包含有关传出数据的信息。

响应头

响应头是一个 Map<String, String>,其中键是头部名称,值是该名称传递的数据。

响应体

响应体是一个 Object? 类型,默认情况下如果没有传递响应体则为 null

响应编码器

响应编码器是一个自定义拦截器类,可以根据值的类型对响应体进行编码。默认情况下,Samba Server 提供了一些内置的响应编码器,例如 StringResponseDecoderNumResponseDecoderBoolResponseDecoderJsonListResponseDecoderJsonMapResponseDecoder

路由

要为 HTTP 服务器创建路由,需要扩展 Route 类,并将其注册到服务器上。还应指定 HTTP 方法和路径作为匹配标准。

静态路由

静态路由是不包含任何动态参数的路由。

class GetUsersRoute extends Route {
  GetUsersRoute() : super(HttpMethod.get, '/users');

  @override
  FutureOr<Response> handler(Request request) {
    return Response.ok(body: 'Users');
  }
}

参数化路由

参数化路由包含一些在路径中的动态路径参数。

非正则表达式路由

非正则表达式路由不包含任何正则表达式在动态路径参数中。

class GetUserRoute extends Route {
  GetUserRoute() : super(HttpMethod.get, '/users/{id}');

  @override
  FutureOr<Response> handler(Request request) {
    final userId = request.pathParameters['id'];
    return Response.ok(body: userId);
  }
}
正则表达式路由

正则表达式路由包含一个在动态路径参数中的正则表达式,该正则表达式由冒号 : 分隔。

class GetUserRoute extends Route {
  GetUserRoute() : super(HttpMethod.get, '/users/{id:^[a-z]+\$}');

  @override
  FutureOr<Response> handler(Request request) {
    final userId = request.pathParameters['id'];
    return Response.ok(body: userId);
  }
}

通配符路由

通配符路由以 * 结束路径。

class UsersWildcardRoute extends Route {
  UsersWildcardRoute() : super(HttpMethod.get, '/users/*');

  @override
  FutureOr<Response> handler(Request request) {
    final remainingPath = request.pathParameters['*'];
    return Response.ok(body: 'Remaining path $remainingPath');
  }
}

WebSocket

WebSocket 是一种用于实现在客户端和服务器之间双向通信的协议。

WebSocket 路由

WebSocket 路由是 Route 类的扩展版本,用于处理 WebSocket 连接。

class ChatSocketRoute extends WebSocketRoute {
  @override
  FutureOr<void> onConnected(WebSocket webSocket) {
    // 发送连接成功的消息给客户端
    webSocket.emit(
      'message',
      {
        'connectionStatus': 'successful',
      },
    );

    // 监听客户端发送的消息
    webSocket.on('message', (data) {
      print('Received message: $data');
    });
  }
}

房间

房间是服务器端的概念,客户端无法控制。服务器可以通过调用 join 函数添加客户端到房间,通过调用 leave 函数移除客户端从房间。

class ChatSocketRoute extends WebSocketRoute {
  @override
  FutureOr<void> onConnected(WebSocket webSocket) {
    // 将客户端加入名为 `discussions` 的房间
    webSocket.join('discussions');

    // 向所有在房间中的客户端发送消息
    emit(
      'message',
      {
        'connectedUserId': webSocket.id,
      },
      rooms: ['discussions'],
    );

    // 移除客户端从名为 `discussions` 的房间
    webSocket.leave('discussions');
  }
}

拦截器

拦截器是一种可以在请求或响应之前或之后修改的类。它可以帮助在返回响应之前阻止进一步的拦截器或路由。

class LoggerInterceptor extends Interceptor {
  @override
  FutureOr<Response?> onInit(Request request) {
    // 当拦截器进入执行范围时触发
    return super.onInit(request);
  }

  @override
  FutureOr<Response> onDispose(Request request, Response response) {
    // 当拦截器退出执行范围时触发
    return super.onDispose(request, response);
  }
}

错误处理

任何在处理请求时发生的错误都会被捕获并传递给 errorHandler

Future<void> main() async {
  final httpServer = HttpServer();
  httpServer.registerErrorHandler((request, response, error, stackTrace) {
    return Response.internalServerError(body: 'Some error has occurred');
  });
  await httpServer.bind(address: '127.0.0.1', port: 8080);
}

关闭服务器

可以通过调用服务器的 shutdown 函数来停止服务器。默认情况下,服务器会优雅地关闭,等待任何未完成的请求完成。如果不希望这种行为,可以将 gracefully 参数设置为 false

Future<void> main() async {
  final httpServer = HttpServer();
  await httpServer.bind(address: '127.0.0.1', port: 8080);

  // 根据适当的条件终止服务器
  if (true) {
    await httpServer.shutdown();
  }
}

更多关于Flutter文件共享服务插件samba_server的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter文件共享服务插件samba_server的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,下面是一个关于如何在Flutter项目中使用samba_server插件来创建文件共享服务的示例代码。请注意,这个插件可能需要在你的设备上具备特定的权限和网络配置,以确保Samba服务能够正常运行。

首先,确保你已经在pubspec.yaml文件中添加了samba_server依赖:

dependencies:
  flutter:
    sdk: flutter
  samba_server: ^最新版本号  # 请替换为实际的最新版本号

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

接下来,你可以在Flutter应用中配置和使用Samba服务。以下是一个基本的示例,展示了如何启动一个Samba服务并共享一个本地目录:

import 'package:flutter/material.dart';
import 'package:samba_server/samba_server.dart';
import 'dart:io';

void main() {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  SambaServer? _sambaServer;
  String _status = "Service not started";

  @override
  void initState() {
    super.initState();
    _startSambaServer();
  }

  @override
  void dispose() {
    _stopSambaServer();
    super.dispose();
  }

  Future<void> _startSambaServer() async {
    Directory sharedDir = Directory('/path/to/shared/directory'); // 替换为你想共享的目录路径
    
    _sambaServer = SambaServer(
      sharedDir: sharedDir,
      username: 'guest',
      password: 'guest', // 这里设置了一个简单的用户名和密码,实际使用中应该更加安全
      workgroupName: 'WORKGROUP',
      serverName: 'MyFlutterSambaServer',
    );

    try {
      await _sambaServer!.start();
      setState(() {
        _status = "Service started successfully";
      });
    } catch (e) {
      setState(() {
        _status = "Failed to start service: $e";
      });
    }
  }

  Future<void> _stopSambaServer() async {
    if (_sambaServer != null) {
      await _sambaServer!.stop();
      setState(() {
        _status = "Service stopped";
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Flutter Samba Server Example'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(
                'Samba Server Status: $_status',
                style: TextStyle(fontSize: 20),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () async {
                  if (_sambaServer!.isRunning) {
                    await _stopSambaServer();
                  } else {
                    await _startSambaServer();
                  }
                },
                child: Text(_sambaServer?.isRunning == true ? 'Stop Server' : 'Start Server'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

注意事项:

  1. 权限:确保你的应用具有访问和共享指定目录的权限。在Android上,你可能需要在AndroidManifest.xml中请求特定的存储权限。
  2. 网络配置:确保你的设备在同一个网络上,并且防火墙或路由器设置不会阻止Samba服务的端口(通常是137, 138, 139, 和445)。
  3. 安全性:上面的示例中使用了简单的用户名和密码(‘guest’),在实际应用中应该使用更安全的认证机制。
  4. 插件版本samba_server插件的API可能会随着版本更新而变化,请参考最新的插件文档进行调整。

这个示例提供了一个基本的框架,你可以根据实际需求进行扩展和修改。

回到顶部