Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Dev #13

Merged
merged 4 commits into from
May 13, 2024
Merged

Dev #13

Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ linter:
- always_declare_return_types
- always_put_control_body_on_new_line
- always_put_required_named_parameters_first
- always_require_non_null_named_parameters
- annotate_overrides
- avoid_bool_literals_in_conditional_expressions
- avoid_double_and_int_checks
Expand All @@ -15,7 +14,6 @@ linter:
- avoid_relative_lib_imports
- avoid_renaming_method_parameters
- avoid_return_types_on_setters
- avoid_returning_null
- avoid_single_cascade_in_expression_statements
- avoid_slow_async_io
- avoid_types_as_parameter_names
Expand All @@ -32,12 +30,9 @@ linter:
- empty_statements
- hash_and_equals
- implementation_imports
- invariant_booleans
- iterable_contains_unrelated_type
- join_return_with_assignment
- library_names
- library_prefixes
- list_remove_unrelated_type
- literal_only_boolean_expressions
- no_duplicate_case_values
- non_constant_identifier_names
Expand All @@ -56,7 +51,6 @@ linter:
- prefer_const_literals_to_create_immutables
- prefer_constructors_over_static_methods
- prefer_contains
- prefer_equal_for_default_values
- prefer_final_fields
- prefer_final_locals
- prefer_foreach
Expand Down
3 changes: 2 additions & 1 deletion lib/src/file_system/entries/ftp_file.dart
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,9 @@ class FtpFile extends FtpEntry {
var result = false;
try {
final downloadFileStream = _client.fs.downloadFileStream(this);
//todo search way to provide file size if necessary
final uploadStream =
secondClient.fs.uploadFileFromStream(fileTo, downloadFileStream);
secondClient.fs.uploadFileFromStream(fileTo, downloadFileStream, 0);
result = await uploadStream;
} finally {
try {
Expand Down
63 changes: 48 additions & 15 deletions lib/src/file_system/ftp_file_system.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
// ignore_for_file: constant_identifier_names

import 'dart:async';

import 'package:pure_ftp/src/file_system/entries/ftp_directory.dart';
Expand All @@ -16,6 +14,9 @@ import 'package:pure_ftp/src/ftp/utils/data_parser_utils.dart';
import 'package:pure_ftp/src/ftp_client.dart';
import 'package:pure_ftp/utils/list_utils.dart';

export 'package:pure_ftp/src/file_system/ftp_transfer.dart'
show OnTransferProgress;

typedef DirInfoCache
= MapEntry<String, Iterable<MapEntry<FtpEntry, FtpEntryInfo>>>;

Expand Down Expand Up @@ -51,7 +52,7 @@ class FtpFileSystem {
FtpDirectory get currentDirectory => _currentDirectory;

FtpDirectory get rootDirectory => FtpDirectory(
path: _rootPath,
path: _rootPath,
client: _client,
);

Expand Down Expand Up @@ -197,21 +198,42 @@ class FtpFileSystem {
.toList();
});

Stream<List<int>> downloadFileStream(FtpFile file) =>
_transfer.downloadFileStream(file);
Stream<List<int>> downloadFileStream(
FtpFile file, {
OnTransferProgress? onReceiveProgress,
}) =>
_transfer.downloadFileStream(
file,
onReceiveProgress: onReceiveProgress,
);

Future<List<int>> downloadFile(FtpFile file) async {
Future<List<int>> downloadFile(
FtpFile file, {
OnTransferProgress? onReceiveProgress,
}) async {
final result = <int>[];
await downloadFileStream(file).listen(result.addAll).asFuture();
await downloadFileStream(
file,
onReceiveProgress: onReceiveProgress,
).listen(result.addAll).asFuture();
return result;
}

Future<bool> uploadFile(FtpFile file, List<int> data,
[UploadChunkSize chunkSize = UploadChunkSize.kb4]) async {
Future<bool> uploadFile(
FtpFile file,
List<int> data, {
UploadChunkSize chunkSize = UploadChunkSize.kb4,
OnTransferProgress? onUploadProgress,
}) async {
final stream = StreamController<List<int>>();
var result = false;
try {
final future = uploadFileFromStream(file, stream.stream);
final future = uploadFileFromStream(
file,
stream.stream,
data.length,
onUploadProgress: onUploadProgress,
);
if (data.isEmpty) {
stream.add(data);
} else {
Expand All @@ -229,6 +251,20 @@ class FtpFileSystem {
return result;
}

Future<bool> uploadFileFromStream(
FtpFile file,
Stream<List<int>> stream,
int fileSize, {
OnTransferProgress? onUploadProgress,
}) async {
return _transfer.uploadFileStream(
file,
stream,
fileSize,
onUploadProgress: onUploadProgress,
);
}

Future<FtpEntryInfo?> getEntryInfo(FtpEntry entry,
{bool fromCache = true}) async {
assert(
Expand All @@ -248,11 +284,6 @@ class FtpFileSystem {
throw UnimplementedError();
}

Future<bool> uploadFileFromStream(
FtpFile file, Stream<List<int>> stream) async {
return _transfer.uploadFileStream(file, stream);
}

FtpFileSystem copy() {
final ftpFileSystem = FtpFileSystem(client: _client.clone());
ftpFileSystem._currentDirectory = _currentDirectory;
Expand All @@ -267,7 +298,9 @@ class FtpFileSystem {
}

enum ListType {
// ignore: constant_identifier_names
LIST(FtpCommand.LIST),
// ignore: constant_identifier_names
MLSD(FtpCommand.MLSD),
;

Expand Down
31 changes: 24 additions & 7 deletions lib/src/file_system/ftp_transfer.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import 'dart:async';
import 'dart:math';
import 'dart:typed_data';

import 'package:pure_ftp/src/file_system/entries/ftp_file.dart';
Expand All @@ -8,22 +9,27 @@ import 'package:pure_ftp/src/ftp/ftp_commands.dart';
import 'package:pure_ftp/src/ftp/ftp_socket.dart';
import 'package:pure_ftp/src/socket/common/client_raw_socket.dart';

typedef OnTransferProgress = Function(int bytes, int total, double percents);

class FtpTransfer {
final FtpSocket _socket;

FtpTransfer({
required FtpSocket socket,
}) : _socket = socket;

Stream<List<int>> downloadFileStream(FtpFile file) {
Stream<List<int>> downloadFileStream(
FtpFile file, {
OnTransferProgress? onReceiveProgress,
}) {
final stream = StreamController<List<int>>();
unawaited(_socket.openTransferChannel((socketFuture, log) async {
final fileSize = await file.size();
FtpCommand.RETR.write(
_socket,
[file.path],
);
//will be closed by the transfer channel
// ignore: close_sinks
final socket = await socketFuture;
final response = await _socket.read();

Expand All @@ -32,11 +38,14 @@ class FtpTransfer {
if (!transferCompleted) {
throw FtpException('Error while downloading file');
}
var total = 0;
var downloaded = 0;
await socket.listen(
(event) {
stream.add(event);
log?.call('Downloaded ${total += event.length} bytes');
downloaded += event.length;
final total = max(fileSize, downloaded);
onReceiveProgress?.call(downloaded, total, downloaded / total * 100);
log?.call('Downloaded ${downloaded} of ${total} bytes');
},
).asFuture();
await _socket.read();
Expand All @@ -48,7 +57,12 @@ class FtpTransfer {
return stream.stream;
}

Future<bool> uploadFileStream(FtpFile file, Stream<List<int>> data) =>
Future<bool> uploadFileStream(
FtpFile file,
Stream<List<int>> data,
int fileSize, {
OnTransferProgress? onUploadProgress,
}) =>
_socket.openTransferChannel((socketFuture, log) async {
FtpCommand.STOR.write(
_socket,
Expand All @@ -64,12 +78,15 @@ class FtpTransfer {
if (!transferCompleted) {
throw FtpException('Error while uploading file');
}
var total = 0;
var uploaded = 0;
final transform = data.transform<Uint8List>(
StreamTransformer.fromHandlers(
handleData: (event, sink) {
sink.add(Uint8List.fromList(event));
log?.call('Uploaded ${total += event.length} bytes');
uploaded += event.length;
final total = max(fileSize, uploaded);
onUploadProgress?.call(uploaded, total, uploaded / total * 100);
log?.call('Downloaded ${uploaded} of ${total} bytes');
},
),
);
Expand Down
39 changes: 21 additions & 18 deletions lib/src/ftp/utils/data_parser_utils.dart
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@ abstract class DataParserUtils {
/// port format (|||xxxxx|) if [isIPV6] is true
///
/// format 227 Entering Passive Mode (192,168,8,36,8,75) if [isIPV6] is false
static int parsePort(FtpResponse response, {
static int parsePort(
FtpResponse response, {
required bool isIPV6,
}) {
if (!response.isSuccessful) {
Expand All @@ -26,12 +27,12 @@ abstract class DataParserUtils {
///
/// port format (|||xxxxx|)
static int _parsePortEPSV(FtpResponse response) {
final message = response.message;
var message = response.message;
final iParOpen = message.indexOf('(');
final iParClose = message.indexOf(')');

if (iParClose > -1 && iParOpen > -1) {
message.substring(iParOpen + 4, iParClose - 1);
message = message.substring(iParOpen + 4, iParClose - 1);
}
return int.parse(message);
}
Expand All @@ -54,22 +55,22 @@ abstract class DataParserUtils {
}

static final RegExp _regexpLIST = RegExp(r''
r'^([\-ld])' // Directory flag [1]
r'([\-rwxs]{9})\s+' // Permissions [2]
r'(\d+)\s+' // Number of items [3]
r'(\w+)\s+' // File owner [4]
r'(\w+)\s+' // File group [5]
r'(\d+)\s+' // File size in bytes [6]
r'(\w{3}\s+\d{1,2}\s+(?:\d{1,2}:\d{1,2}|\d{4}))\s+' // date[7]
r'(.+)$' //entry name[8]
);
r'^([\-ld])' // Directory flag [1]
r'([\-rwxs]{9})\s+' // Permissions [2]
r'(\d+)\s+' // Number of items [3]
r'(\w+)\s+' // File owner [4]
r'(\w+)\s+' // File group [5]
r'(\d+)\s+' // File size in bytes [6]
r'(\w{3}\s+\d{1,2}\s+(?:\d{1,2}:\d{1,2}|\d{4}))\s+' // date[7]
r'(.+)$' //entry name[8]
);

static final _regexpLISTSii = RegExp(r''
r'^(.{8}\s+.{7})\s+' //date[1]
r'(.{0,5})\s+' //type file or dir [2]
r'(\d{0,24})\s+' //size [3]
r'(.+)$' //entry name [4]
);
r'^(.{8}\s+.{7})\s+' //date[1]
r'(.{0,5})\s+' //type file or dir [2]
r'(\d{0,24})\s+' //size [3]
r'(.+)$' //entry name [4]
);

/// Parse the [response] from the LIST|MLSD command
static Map<FtpEntry, FtpEntryInfo?> parseListDirResponse(
Expand Down Expand Up @@ -120,7 +121,9 @@ abstract class DataParserUtils {
return result;
}

static MapEntry<String, FtpEntryInfo>? _parseListServerEntry(String line,) {
static MapEntry<String, FtpEntryInfo>? _parseListServerEntry(
String line,
) {
final match = _regexpLIST.firstMatch(line);
if (match == null) {
return null;
Expand Down
4 changes: 3 additions & 1 deletion lib/src/socket/html/client_raw_socket.dart
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ class ClientRawSocketImpl extends ClientRawSocket {
}

@override
Future<ClientRawSocket> secureSocket({bool ignoreCertificateErrors = false}) async {
Future<ClientRawSocket> secureSocket({
bool ignoreCertificateErrors = false,
}) async {
throw UnimplementedError();
}

Expand Down
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ environment:
sdk: '>=2.18.6 <4.0.0'

dependencies:
meta: ^1.10.0
meta: ^1.15.0

dev_dependencies:
lints: ^2.0.1
test: ^1.22.1
lints: ^4.0.0
test: ^1.25.5
yaml: ^3.1.2
Loading
Loading