I'm working on an Android project that requires FTP download to be paused/resumed.
Here is the code I use for FTP connection:
ftpClient.setConnectTimeout(25000);
ftpClient.login("login", "password");
ftpClient.changeWorkingDirectory("/audio");
ftpClient.enterLocalPassiveMode();
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
then I start download:
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile));
byte[] bytesArray = new byte[4096];
int bytesRead = -1;
totalRead = 0;
if (localFileSize > 0) {
ftpClient.setRestartOffset(localFileSize);
ftpClient.restart(localFileSize);
}
InputStream inputStream = ftpClient.retrieveFileStream(fileName);
while ((bytesRead = inputStream.read(bytesArray)) != -1) {
totalRead += bytesRead;
outputStream.write(bytesArray, (int) localFileSize, bytesRead);
}
success = ftpClient.completePendingCommand();
and I try to pause using abort
like this:
if (ftpClient.abort()) {
//connection aborted!;
}
But it seems that abort
doesn't work while there is an active download as mentioned here: https://issues.apache.org/jira/browse/NET-419
Is there any way I can perform pause/resume for FTP downloads in Android?
I used the same AsyncTask
for connect, download and abort operations:
protected Void doInBackground(Integer... params) {
int command = params.length > 0 ? params[0] : 0;
switch (command) {
case CONNECT:
connect();
break;
case DOWNLOAD:
download();
break;
case PAUSE:
abortConnection();
break;
}
return null;
}
To make sure there is only one task running each time I used Singleton design pattern
public static FtpConnectTask getInstance(FTPClientWrapper ftpClient) {
if (instance != null) {
if (instance.getStatus().name().toLowerCase().equals("running"){
instance.cancel(true);
}
if (instance.getStatus().name().toLowerCase().equals("finished")) {
// task finished!
}
}
instance = new FtpConnect(uiListener, ftpClientW);
return instance;
}
This is code of download()
method:
we look for local file size each time the download starts, then we use this size as starting point
//create local file
File localFile = new File(outDir, FILE_NAME));
// get file size if the file exists
long localFileSize = localFile.length();
//retrieve file from server
try {
OutputStream outputStream = new BufferedOutputStream(new FileOutputStream(localFile, true));
byte[] bytesArray = new byte[4096];
int bytesRead;
int totalRead = (int) localFileSize;
ftpClient.restart(localFileSize);
InputStream inputStream = ftpClient.retrieveFileStream(REMOTE_FILE);
while ((bytesRead = inputStream.read(bytesArray)) != -1) {
totalRead += bytesRead;
outputStream.write(bytesArray, 0, bytesRead);
// break the loop when AsyncTask is cancelled
if(isCancelled()){
break;
}
}
if (ftpClient.completePendingCommand()) {
// Task completed!
}
inputStream.close();
outputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
This is code of abortConnection()
if (ftpClient.isConnected()) {
try {
if (ftpClient.abort()) {
// Connection aborted!
}
} catch (IOException e) {
e.printStackTrace();
}
} else {
// Not connected!
}
To resume your download just call
download()
again.