94 lines
4.0 KiB
Dart
94 lines
4.0 KiB
Dart
// lib/services/ftp_service.dart
|
|
|
|
import 'dart:io';
|
|
import 'package:flutter/foundation.dart';
|
|
import 'package:ftpconnect/ftpconnect.dart';
|
|
import 'package:environment_monitoring_app/services/server_config_service.dart';
|
|
// --- ADDED: Import for the new service that manages the retry queue ---
|
|
import 'package:environment_monitoring_app/services/retry_service.dart';
|
|
// --- ADDED: Import for the local database helper ---
|
|
import 'package:environment_monitoring_app/services/api_service.dart';
|
|
|
|
class FtpService {
|
|
final ServerConfigService _serverConfigService = ServerConfigService();
|
|
// --- REMOVED: This creates an infinite loop with RetryService ---
|
|
// final RetryService _retryService = RetryService();
|
|
final DatabaseHelper _dbHelper = DatabaseHelper(); // --- ADDED: Instance of DatabaseHelper to get all configs ---
|
|
|
|
/// Uploads a single file to the active server's FTP.
|
|
///
|
|
/// [fileToUpload] The local file to be uploaded.
|
|
/// [remotePath] The destination path on the FTP server (e.g., '/uploads/images/').
|
|
/// Returns a map with 'success' and 'message' keys.
|
|
// --- MODIFIED: Method now attempts to upload to multiple servers ---
|
|
Future<Map<String, dynamic>> uploadFile(File fileToUpload, String remotePath) async {
|
|
final configs = await _dbHelper.loadFtpConfigs() ?? []; // Get all FTP configs
|
|
final latestConfigs = configs.take(2).toList(); // Limit to the two latest configs
|
|
|
|
if (latestConfigs.isEmpty) {
|
|
return {'success': false, 'message': 'FTP credentials are not configured or selected.'};
|
|
}
|
|
|
|
// Loop through each of the two latest configurations and attempt to upload
|
|
for (final configMap in latestConfigs) {
|
|
final config = configMap['config_json']; // The data is nested under this key
|
|
final ftpHost = config?['ftp_host'] as String?;
|
|
final ftpUser = config?['ftp_user'] as String?;
|
|
final ftpPass = config?['ftp_pass'] as String?;
|
|
final ftpPort = config?['ftp_port'] as int? ?? 21;
|
|
|
|
if (ftpHost == null || ftpUser == null || ftpPass == null) {
|
|
debugPrint('FTP: Configuration is incomplete. Skipping to next server if available.');
|
|
continue;
|
|
}
|
|
|
|
final ftpConnect = FTPConnect(
|
|
ftpHost,
|
|
user: ftpUser,
|
|
pass: ftpPass,
|
|
port: ftpPort,
|
|
showLog: kDebugMode, // Show logs only in debug mode
|
|
timeout: 60, // --- MODIFIED: Set the timeout to 60 seconds ---
|
|
);
|
|
|
|
try {
|
|
debugPrint('FTP: Connecting to $ftpHost...');
|
|
await ftpConnect.connect();
|
|
|
|
debugPrint('FTP: Uploading file ${fileToUpload.path} to $remotePath...');
|
|
bool res = await ftpConnect.uploadFileWithRetry(
|
|
fileToUpload,
|
|
pRemoteName: remotePath,
|
|
pRetryCount: 3, // --- MODIFIED: Retry three times on failure ---
|
|
);
|
|
|
|
await ftpConnect.disconnect(); // Disconnect immediately upon success
|
|
if (res) {
|
|
debugPrint('FTP upload to $ftpHost succeeded.');
|
|
return {'success': true, 'message': 'File uploaded successfully via FTP.'};
|
|
} else {
|
|
debugPrint('FTP upload to $ftpHost failed after retries. Trying next server.');
|
|
continue; // Move to the next configuration in the loop
|
|
}
|
|
} catch (e) {
|
|
debugPrint('FTP upload to $ftpHost failed with an exception. Trying next server. Error: $e');
|
|
try {
|
|
// Attempt to disconnect even if an error occurred during connect/upload
|
|
await ftpConnect.disconnect();
|
|
} catch (_) {
|
|
// Ignore errors during disconnect
|
|
}
|
|
continue; // Move to the next configuration in the loop
|
|
}
|
|
}
|
|
|
|
// If the loop completes and no server was successful, queue for manual retry.
|
|
final retryService = RetryService();
|
|
debugPrint('All FTP upload attempts failed. Queueing for manual retry.');
|
|
await retryService.addFtpToQueue(
|
|
localFilePath: fileToUpload.path,
|
|
remotePath: remotePath
|
|
);
|
|
return {'success': false, 'message': 'All FTP upload attempts failed and have been queued for manual retry.'};
|
|
}
|
|
} |