7
votes

I'm developing an applet to allow FTP upload from a webapp...

The send operation is working fine, but I'd like to able to cancel a file storing in progress.

I'm not very fluent with threads. My first attempt was to call ftp.abort() in the cancel thread, but the abort method was only called when the storeFile method finished, like if the send thread was locking the ftp object.

So I changed the code to interrupt the send thread and check it in the copy stream listener. The file storing stops as expected, but ftp.abort() call hangs the application, it never complete.

Any ideas?

Thanks, Philip

Send operation:

  botaoEnviar.setEnabled(false);
  botaoCancelar.setEnabled(true);
  textField.requestFocus();

  threadEnvio = new Thread(new Runnable()
  {
     @Override
     public void run()
     {            
        FileInputStream fis = null;
        try
        {
           if(arquivoSelecionado == null)
           {
              throw new IllegalArgumentException("Arquivo deve ser informado");
           }

           try
           {
              ftp = new FTPClient();
              ftp.connect("192.168.1.243");
           }
           catch(Exception e)
           {
              throw new FtpConnectionException("Não foi possível conectar no servidor FTP", e);
           }

           if(!ftp.login("c001", "0AJF2J36"))
           {
              throw new IllegalArgumentException("Não foi possível autenticar no servidor FTP");
           }

           ftp.setFileType(FTPClient.BINARY_FILE_TYPE);

           ftp.setCopyStreamListener(new CopyStreamAdapter()
           {                  
              @Override
              public void bytesTransferred(long totalBytesTransferred, int bytesTransferred, long streamSize)
              {
                 if(threadEnvio.isInterrupted())
                 {
                    try
                    {
                       ftp.abort();                           
                    }
                    catch(IOException ex)
                    {
                       handleException(ex);
                    }
                 }
                 else
                 {
                    int percent = (int) (totalBytesTransferred * 100 / arquivoSelecionado.length());
                    progressBar.setValue(percent);
                 }
              }
           });

           fis = new FileInputStream(arquivoSelecionado);               
           if(ftp.storeFile(arquivoSelecionado.getName(), fis))
           {
              JOptionPane.showMessageDialog(null, "Arquivo enviado com suceso");
           }
           else
           {
              JOptionPane.showMessageDialog(null, "Não foi possível enviar o arquivo", "Erro", JOptionPane.ERROR_MESSAGE);
           }

           ftp.logout();
        }            
        catch(Exception e)
        {
           handleException(e);
        }
        finally
        {
           if(fis != null)
           {
              try
              {
                 fis.close();
              }
              catch(IOException ex)
              {
                 handleException(ex);
              }
           }

           if(ftp != null)
           {
              try
              {
                 ftp.disconnect();
              }
              catch(IOException ex)
              {
                 handleException(ex);
              }
           }

           progressBar.setValue(0);
           botaoEnviar.setEnabled(true);               
           botaoCancelar.setEnabled(false);               
        }
     }
  });
  threadEnvio.start();

Cancel operation:

botaoCancelar.setEnabled(false);

  new Thread(new Runnable()
  {
     @Override
     public void run()
     {
        try
        {               
           threadEnvio.interrupt();
        }
        catch(Exception ex)
        {
           handleException(ex);
        }
        finally
        {
           botaoCancelar.setEnabled(true);               
        }
     }

  }).start();
1
Yeah would be nice if commons net FTPClient had API to abort a transfer, for example using the copy listener, where you can return a boolean as false to abort the transfer. - Claus Ibsen
Instead of thinking in terms interrupting the thread, try to make the ftp = new FTPClient() accessible. When the user clicks on the Cancel button, add a event to that button that will get the ftp and run the method abor() on the ftp instance. - vianna77

1 Answers

1
votes

interrupting a thread like this isn't true and cause your thread wait for some secs(or even millis) at exactly which line that compiler is reading in your thread
the only way that you can abort your ftp upload is making thread sleep some time and then abort your upload and after all wait for thread to complete itself
see this :

   try {
            try {
                    Thread.currentThread();
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                } 

            try {
                    mFTP.abort();
                } catch (IOException e) {
                    e.printStackTrace();
                }
    } catch (NetworkOnMainThreadException e) {

    }