pkg_sftp_file_collector version: 1.0.0

Published 2025-05-26

reinbeumer

sdk | dart
repository | svn
platform | generic
status | n/a
  • Readme
  • Changelog
  • Versions

SFTP File Collector

A Dart package for collecting files from SFTP servers with support for recursive traversal, maintaining folder structures, and automated file archiving. This package simplifies the process of downloading and managing files from SFTP sources.

Features

  • Connect to SFTP servers using either password or SSH key authentication
  • List files in remote directories
  • Download files while optionally preserving the remote folder structure
  • Recursively traverse directories to collect all nested files
  • Move files to archive directories after successful download
  • Comprehensive logging support

Getting started

Prerequisites

  • Dart SDK >=3.8.0 <4.0.0
  • Dependencies:
    • logging: ^1.3.0
    • path: ^1.9.1
    • dartssh2: ^2.12.0

Installation

Add the following to your pubspec.yaml:

dependencies:
  pkg_sftp_file_collector: ^1.0.0 # Replace with the latest version

Then run:

dart pub get

Usage

Import the package:

import 'package:pkg_sftp_file_collector/pkg_sftp_file_collector.dart';

Basic Example

import 'dart:io';
import 'package:logging/logging.dart';
import 'package:pkg_sftp_file_collector/pkg_sftp_file_collector.dart';

Future<void> main() async {
  // Setup logging
  Logger.root.level = Level.FINE;
  Logger.root.onRecord.listen((final LogRecord record) {
    stdout.writeln('${record.level.name}: ${record.time}: [${record.loggerName}] ${record.message}');
  });
  
  // Configure SFTP connection using ModelSftpFileConnector
  final ModelSftpFileConnector connectionDetails = ModelSftpFileConnector(
    host: '192.168.22.42',
    username: 'username',
    passwordOrKey: '/path/to/.ssh/id_rsa', // or password string
    port: 22,
    remotePath: '/remote/data/source', // Source directory for operations like moveFile
    sftpRootPath: '/remote/data/source', // Root path for listing and as base for relative paths
    localPath: 'assets/', // Local directory to download files
    sftpArchivePath: '/remote/data/archive', // Archive directory on the SFTP server
    retainSftpFolderStructure: true,
    sftpRootPathOnly: false, // Set to true to avoid recursive directory traversal in collectRecursive logic
    sftpMoveToArchive: true, // Set to true to enable moving files to archive after download
  );

  final SftpFileCollector collector = SftpFileCollector(conn: connectionDetails);

  try {
    // Connect to the SFTP server
    await collector.connect();
    
    List<String> downloadedFiles;
    if (connectionDetails.sftpRootPathOnly) {
      // List files in the sftpRootPath
      downloadedFiles = await collector.listFiles();
      for (final String file in downloadedFiles) {
        // Download each file
        final (bool success, _) = await collector.downloadFile(fileName: file);
        if (!success) {
          // Handle download failure if necessary
          Logger.root.warning('Failed to download $file');
          // Remove from list if we only want to archive successfully downloaded files
          // This part depends on desired behavior, for simplicity, keeping it as is.
        }
      }
    } else {
      // Download files recursively starting from conn.remotePath (which is sftpRootPath in this example)
      downloadedFiles = await collector.collectRecursive(remotePath: connectionDetails.remotePath);
    }
    
    // Move downloaded files to archive if sftpMoveToArchive is true
    if (connectionDetails.sftpMoveToArchive) {
      for (final String file in downloadedFiles) {
        // fileName for moveFile is relative to conn.remotePath
        await collector.moveFile(fileName: file);
      }
    }
  } catch (e) {
    print('Error: $e');
  } finally {
    // Always disconnect when done
    collector.disconnect();
  }
}

Non-recursive File Collection

If you only want to collect files from a specific directory without recursion, configure ModelSftpFileConnector accordingly:

Future<void> main() async {
  // Configure for non-recursive collection
  final ModelSftpFileConnector connectionDetails = ModelSftpFileConnector(
    host: 'host',
    username: 'username',
    passwordOrKey: 'password', // or path to key file
    port: 22,
    sftpRootPath: '/remote/path', // The specific directory to list and download from
    localPath: 'downloads/',
    retainSftpFolderStructure: false, // Typically false for flat download structure
    sftpRootPathOnly: true, // This flag is key for non-recursive behavior if using a combined logic
                             // but listFiles() itself is non-recursive.
    // sftpMoveToArchive can be true or false based on requirements
    // remotePath (source directory for moveFile, typically same as sftpRootPath if using file names from listFiles) and sftpArchivePath would be needed if sftpMoveToArchive is true
  );

  final SftpFileCollector collector = SftpFileCollector(conn: connectionDetails);

  try {
    // List and download files
    await collector.connect();
    // listFiles uses conn.sftpRootPath
    final List<String> files = await collector.listFiles(); 

    for (final String file in files) {
      // downloadFile uses conn.sftpRootPath as base for fileName, and conn.localPath for destination
      final (bool success, _) = await collector.downloadFile(fileName: file);
      if (success) {
        print('Downloaded $file successfully.');
        // Optionally move to archive if configured
        // if (connectionDetails.sftpMoveToArchive) {
        //   await collector.moveFile(fileName: file);
        // }
      } else {
        print('Failed to download $file.');
      }
    }
  } catch (e) {
    print('Error: $e');
  } finally {
    collector.disconnect();
  }
}

See the example/ folder for a complete example implementation.

Additional information

This package is designed for reliable file collection from SFTP servers in production environments. It supports error handling, comprehensive logging, and is built on the dartssh2 package.

License

See the LICENSE file for details.

Changelog

1.0.0 - 2025-05-26

Changed

  • Refactored.

0.0.7 - 2025-05-26

Changed

  • Refactored.

0.0.6 - 2025-05-22

Changed

  • Version bump from 0.0.5 to 0.0.6 (lints -> 6.0.0 (was 5.1.1)).

0.0.5 - 2025-05-22

Changed

  • Version bump from 0.0.4 to 0.0.5 (lints -> 5.1.1 (was 6.0.0)).

0.0.4 - 2025-05-22

Changed

  • Version bump from 0.0.3 to 0.0.4 (test -> 1.26.2 (was 1.26.1)).

0.0.3 - 2025-05-21

Changed

  • Version bump from 0.0.2 to 0.0.3 (test -> 1.26.1 (was 1.24.0)).

0.0.2 - 2025-05-21

Changed

  • Version bump from 0.0.1 to 0.0.2 (lints -> 5.1.1 (was 5.0.0)).

0.0.1 - 2025-05-20

  • Initial version.

1.0.0

2025-05-26 download

0.0.7

2025-05-26 download

0.0.6

2025-05-22 download