0

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?

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
android.dev
  • 26
  • 1
  • 7

2 Answers2

0

If you really want to pause the download only (as opposite to abort/reconnect/resume), then all you need to do, is temporarily pause the while loop that writes to the data connection stream.

See How to pause/resume thread in Android?

Community
  • 1
  • 1
Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
  • thank you for your answer @Martin Prikryl, I tried it and found the download still going in background until the file completes. – android.dev Sep 17 '15 at 10:39
  • How can it continue, if you do not provide data to the stream? All it can possibly do, is to finish uploading a buffered data that you wrote to the stream previously. But it cannot continue until the file completes. Where it would get the data from? – Martin Prikryl Sep 17 '15 at 10:54
0

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.

android.dev
  • 26
  • 1
  • 7