Skip to content

Commit

Permalink
File Download
Browse files Browse the repository at this point in the history
  • Loading branch information
virtualmarc committed Feb 6, 2020
1 parent a8fcbcc commit 20e677e
Show file tree
Hide file tree
Showing 7 changed files with 131 additions and 33 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
- Change Transfer mode (default is binary)
- Set Remote file name
- Small performance optimization
- Download Files

## 0.1.0

Expand Down
75 changes: 75 additions & 0 deletions lib/src/commands/filedownload.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import 'dart:io';

import '../ftpexceptions.dart';
import '../ftpsocket.dart';
import '../transfermode.dart';
import '../debug/debuglog.dart';
import '../util/transferutil.dart';

class FileDownload {
final FTPSocket _socket;
final TransferMode _mode;
final DebugLog _log;

/// File Download Command
FileDownload(this._socket, this._mode, this._log);

void downloadFile(String sRemoteName, File fLocalFile) {
_log.log('Download $sRemoteName to ${fLocalFile.path}');

// Transfer Mode
TransferUtil.setTransferMode(_socket, _mode);

// Enter passive mode
_socket.sendCommand('PASV');

String sResponse = _socket.readResponse();
if (!sResponse.startsWith('227 ')) {
throw FTPException('Could not start Passive Mode', sResponse);
}

int iPort = TransferUtil.parsePort(sResponse);

_socket.sendCommand('RETR $sRemoteName');
sResponse = _socket.readResponse(true);
if (sResponse.startsWith('550 ')) {
throw FTPException('Remote File $sRemoteName does not exist!', sResponse);
}

// Transfer file
RandomAccessFile fRAFile = fLocalFile.openSync(mode: FileMode.writeOnly);

// Data Transfer Socket
_log.log('Opening DataSocket to Port $iPort');
RawSynchronousSocket dataSocket = RawSynchronousSocket.connectSync(_socket.host, iPort);

int iToRead = 0;
int iRead = 0;

do {
if (iToRead > 0) {
List<int> buffer = List<int>(iToRead);
dataSocket.readIntoSync(buffer);
fRAFile.writeFromSync(buffer);
iRead += iToRead;
}

iToRead = dataSocket.available();

if (iToRead == 0 || iRead == 0) {
sleep(Duration(milliseconds: 500));
iToRead = dataSocket.available();
}
} while(iToRead > 0 || iRead == 0);

_log.log('Downloaded: $iRead B');

dataSocket.closeSync();
fRAFile.flushSync();
fRAFile.closeSync();

_socket.readResponse();

_log.log('File Downloaded!');
}
}
38 changes: 6 additions & 32 deletions lib/src/commands/fileupload.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import 'dart:io';

import 'package:ftpclient/src/debug/debuglog.dart';
import 'package:path/path.dart';

import '../ftpexceptions.dart';
import '../ftpsocket.dart';
import '../transfermode.dart';
import '../debug/debuglog.dart';
import '../util/transferutil.dart';

class FileUpload {
static const int _BUFFER_SIZE = 1024 * 1024;
Expand All @@ -21,20 +22,7 @@ class FileUpload {
_log.log('Upload File: ${fFile.path}');

// Transfer Mode
switch(_mode) {
case TransferMode.ascii:
// Set to ASCII mode
_socket.sendCommand('TYPE A');
_socket.readResponse();
break;
case TransferMode.binary:
// Set to BINARY mode
_socket.sendCommand('TYPE I');
_socket.readResponse();
break;
default:
break;
}
TransferUtil.setTransferMode(_socket, _mode);

// Enter passive mode
_socket.sendCommand('PASV');
Expand All @@ -44,7 +32,7 @@ class FileUpload {
throw FTPException('Could not start Passive Mode', sResponse);
}

int iPort = _parsePort(sResponse);
int iPort = TransferUtil.parsePort(sResponse);

// Store File
String sFilename = sRemoteName;
Expand All @@ -61,7 +49,7 @@ class FileUpload {
RandomAccessFile fRAFile = fFile.openSync(mode: FileMode.read);
int iRead = 0;
final int iSize = fRAFile.lengthSync();
_log.log('File Size: $iSize');
_log.log('File Size: $iSize B');

while (iRead < iSize) {
int iEnd = _BUFFER_SIZE;
Expand All @@ -76,7 +64,7 @@ class FileUpload {
iRead += iEnd;
}

_log.log('Uploaded: $iRead');
_log.log('Uploaded: $iRead B');

dataSocket.closeSync();
fRAFile.closeSync();
Expand All @@ -85,18 +73,4 @@ class FileUpload {

_log.log('File Uploaded!');
}

/// Parse the Passive Mode Port from the Servers [sResponse]
int _parsePort(String sResponse) {
int iParOpen = sResponse.indexOf('(');
int iParClose = sResponse.indexOf(')');

String sParameters = sResponse.substring(iParOpen + 1, iParClose);
List<String> lstParameters = sParameters.split(',');

int iPort1 = int.parse(lstParameters[lstParameters.length - 2]);
int iPort2 = int.parse(lstParameters[lstParameters.length - 1]);

return (iPort1 * 256) + iPort2;
}
}
6 changes: 6 additions & 0 deletions lib/src/ftpclient_base.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import 'dart:io';

import 'package:ftpclient/src/commands/filedownload.dart';
import 'package:ftpclient/src/commands/fileupload.dart';
import 'package:ftpclient/src/debug/debuglog.dart';
import 'package:ftpclient/src/debug/nooplog.dart';
Expand Down Expand Up @@ -50,6 +51,11 @@ class FTPClient {
FileUpload(_socket, mode, _log).uploadFile(fFile, sRemoteName);
}

/// Download the Remote File [sRemoteName] to the local File [fFile]
void downloadFile(String sRemoteName, File fFile, {TransferMode mode = TransferMode.binary}) {
FileDownload(_socket, mode, _log).downloadFile(sRemoteName, fFile);
}

/// Create a new Directory with the Name of [sDirectory] in the current directory
/// Returns `true` if the directory was created successfully
/// Returns `false` if the directory could not be created or already exists
Expand Down
5 changes: 5 additions & 0 deletions lib/src/ftpexceptions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,9 @@ class FTPException implements Exception {
final String response;

FTPException(this.message, [this.response]);

@override
String toString() {
return 'FTPException: $message (Response: $response)';
}
}
3 changes: 2 additions & 1 deletion lib/src/ftpsocket.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,11 @@ class FTPSocket {

/// Send a command to the FTP Server
void sendCommand(String sCommand) {
_log.log('> $sCommand');
if (_socket.available() > 0) {
readResponse();
}

_log.log('> $sCommand');
_socket.writeFromSync(_codec.encode('$sCommand\r\n'));
}

Expand Down
36 changes: 36 additions & 0 deletions lib/src/util/transferutil.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import '../ftpsocket.dart';
import '../transfermode.dart';

class TransferUtil {
/// Set the Transfer mode on [socket] to [mode]
static void setTransferMode(FTPSocket socket, TransferMode mode) {
switch(mode) {
case TransferMode.ascii:
// Set to ASCII mode
socket.sendCommand('TYPE A');
socket.readResponse();
break;
case TransferMode.binary:
// Set to BINARY mode
socket.sendCommand('TYPE I');
socket.readResponse();
break;
default:
break;
}
}

/// Parse the Passive Mode Port from the Servers [sResponse]
static int parsePort(String sResponse) {
int iParOpen = sResponse.indexOf('(');
int iParClose = sResponse.indexOf(')');

String sParameters = sResponse.substring(iParOpen + 1, iParClose);
List<String> lstParameters = sParameters.split(',');

int iPort1 = int.parse(lstParameters[lstParameters.length - 2]);
int iPort2 = int.parse(lstParameters[lstParameters.length - 1]);

return (iPort1 * 256) + iPort2;
}
}

0 comments on commit 20e677e

Please sign in to comment.