【问题标题】:JSch upload with progress monitor带有进度监视器的 JSch 上传
【发布时间】:2013-06-12 07:35:36
【问题描述】:

我尝试使用进度条实现 SFTP 上传。

可惜进度条没有更新……

这是我的代码的一部分:

public class MainView extends JFrame implements SftpProgressMonitor {

    private static final Logger LOG = Logger.getLogger(MainView.class);
    private String _source;
    private JProgressBar _progressBar;
    private JButton _button;

    public MainView() {
        initComponents();
    }

    void initComponents() {
        _button = new JButton("Send");
        _button.addActionListener(new ActionListener() {
            // If clicked, send event to controller...
        });
        _progressBar = new JProgressBar();
        // Do init stuff here
        // ...
    }

    @Override
    public boolean count(long byteTransfered) {
        int transfered = _progressBar.getValue();
        transfered += byteTransfered;
        _progressBar.setValue(transfered);
        return true;
    }

    @Override
    public void end() {
        LOG.info("Transfer of "+_source+" finished!");
    }

    @Override
    public void init(int op, String src, String dest, long max) {
        _progressBar.setValue(0);
        _progressBar.setMinimum(0);
        _progressBar.setMaximum((int) max);
        _source = src;
    }
}


public class Controller {

    private final MainView _view;
    private final SftpClient _ftp;
    private final Server _server;

    public Controller() {
        _server = new Server("192.168.0.1");
        _view = new MainView();
        _ftp = new SftpClient(_server);

        _view.setVisible(true);
    }

    public void send() {
        Executor executor = Executors.newSingleThreadExecutor();
        executor.execute(new Runnable() {
            public void run() {
                File testFile = new File("/PathToFile/file.txt");
                String remoteDir = "/MyRemoteDir/";
                _ftp.put(testFile, remoteDir, testFile.getName(), _view);
            }
        });
    }

    public static void main(String[] args) {
        Controller controller = new Controller();
    }
}

public class SftpClient {
    private static final Logger LOG = Logger.getLogger(SftpClient.class);

    /** Connection port number */
    public static final int PORT = 22;

    /** SECURED protocol name */
    public static final String PROTOCOL = "sftp";

    /** Connection time out in milliseconds */
    public static final int TIME_OUT = 3000;

    private Server _server;
    /** This class serves as a central configuration point, and as a factory for Session objects configured with these settings */
    private JSch _client;
    /** A session represents a connection to a SSH server */
    private Session _session;
    /** Channel connected to a SECURED server (as a subsystem of the SSH server) */
    private ChannelSftp _channelSftp;

    /**
     * Value returned by the last executed command.
     */
    private int _exitValue;

    public SftpClient(Server server) {
        _client = new JSch();
        _server = server;
    }

    protected void connect() throws AuthenticationException, Exception {
        try {
            if (_client == null) {
                _client = new JSch();
            }
            if (_session == null) {
                _session = _client.getSession(_server.getLogin(), _server.getAddress(), PORT);
                _session.setConfig("StrictHostKeyChecking", "no");
                _session.setPassword(_server.getPassword());
                if (LOG.isDebugEnabled()) {
                    LOG.debug("Connecting to "+_server.getAddress()+" with login "+_server.getLogin()+"...");
                }
            }
            if (!_session.isConnected()) {
                _session.connect(TIME_OUT);
            }

            if(_channelSftp == null || _channelSftp.isConnected() == false) {
                Channel c = _session.openChannel(PROTOCOL);
                c.connect();
                // disconnect previous channel if it has not been killed properly
                if (_channelSftp != null && _channelSftp.isConnected()) {
                    _channelSftp.disconnect();
                }
                _channelSftp = (ChannelSftp) c;             
            }

            if (LOG.isInfoEnabled()) {
                LOG.info("Connected to "+_server.getAddress()+" with login "+_server.getLogin());
            }
        } catch(JSchException e) {
            if ("Auth fail".equals(e.getMessage())) {
                throw new AuthenticationException(e);
            } else {
                throw new Exception(e);
            }
        }
    }

    protected void connect(String path) throws AuthenticationException, Exception {
        connect();
        if (_channelSftp != null && _channelSftp.isConnected()) {
            _channelSftp.cd(path);
        }
    }

    @Override
    public void disconnect() {
        if (_channelSftp != null && _channelSftp.isConnected()) {
            _channelSftp.disconnect();
            _channelSftp.exit();
        }
        if (_session != null && _session.isConnected()) {
            _session.disconnect();
            if (LOG.isInfoEnabled()) {
                LOG.info("SECURED FTP disconnected");
            }
        }
    }

    @Override
    public void put(File localFile, String destPath, SftpProgressMonitor monitor) throws Exception {
        put(localFile, destPath, localFile.getName(), monitor);
    }

    @Override
    public void put(File localFile, String destPath, String remoteFileName, SftpProgressMonitor monitor) throws Exception {
        if (LOG.isInfoEnabled()) {
            LOG.info("Send file "+localFile+" to "+_server+" in "+destPath);
        }
        if (localFile == null) {
            _exitValue = -1;
            LOG.error("The given local file is null. Aborting tranfer.");
            return;
        }
        if (!localFile.exists()) {
            _exitValue = -1;
            LOG.error("'"+localFile+"' doesn't exist. Aborting tranfer.");
            return;
        }
        if(!localFile.canRead()) {
            _exitValue = -1;
            LOG.error("Cannot read '"+localFile+"'. Aborting tranfer.");
            return;         
        }

        final InputStream input = new BufferedInputStream(new FileInputStream(localFile));
        if (input == null || input.available() <= 0) {
            _exitValue = -1;
            LOG.error("Cannot read file "+localFile);
            return;
        }
        try {
            connect(destPath);
            _channelSftp.put(input, remoteFileName, monitor);
            _exitValue = _channelSftp.getExitStatus();

        } catch(SftpException e){
            throw new IOException(e);
        } finally {
            if (_channelSftp != null && _channelSftp.isConnected()) {
                _channelSftp.disconnect();
                _channelSftp.exit();
            }
            IOUtils.closeQuietly(input);
        }
    }
}

永远不会调用count() 方法。 init 的源字符串和目标字符串都包含-。我做错了吗?

【问题讨论】:

    标签: java progress-bar sftp jsch


    【解决方案1】:

    我已经更改了我的代码,它现在可以工作了。我不再使用put(InputStream src, String dst, int mode),而是使用put(String src, String dst, SftpProgressMonitor monitor)

    我还实现了一个DefaultBoundedRangeModel 类。它直接修改了 JProgressBar,这对我来说更有趣,因为我有几个文件要传输。

    public class ProgressModel extends DefaultBoundedRangeModel implements SftpProgressMonitor {
    
        /** Logger */
        private static Logger LOG = Logger.getLogger(ProgressModel.class);
        private String _fileBeingTransfered;
    
        /**
         * Constructs the model.
         */
        public ProgressModel() {
            _fileBeingTransfered = "";
        }
    
        @Override
        public boolean count(long count) {
            int value = (int) (getValue() + count);
            setValue(value);
            fireStateChanged();
            if(value < getMaximum()) {
                return true;
            } else {
                return false;
            }
        }
    
        @Override
        public void end() {
            LOG.info(_fileBeingTransfered+" transfert finished.");
            if(getValue() == getMaximum()) {
                LOG.info("All transfers are finished!");
            }
        }
    
        @Override
        public void init(int op, String src, String dest, long max) {
            LOG.info("Transfering "+src+" to "+dest+" | size: "+max);
            _fileBeingTransfered = src;
        }
    }
    

    我不知道是什么导致了我的问题。也许是 put 方法。

    【讨论】:

      【解决方案2】:

      为了获得更新,您必须向 FTP 客户端发送对监视器的引用。你这样做:

      _ftp.put(testFile, remoteDir, testFile.getName(), _view);

      但是_view 是什么?它是 Controller 类的 private final 字段,它永远不会被初始化。因此它是null。您在类MainView 中实现了您的回调方法count(),但不向FTP 客户端发送对它的引用。我不知道你在哪里创建Controller 的实例,但你应该将MainView 的实例的引用传递给它。

      【讨论】:

      • 对不起,我剪掉了代码,去掉了Controller的构造函数。如果它让您感到困惑,我将编辑代码。
      • 我很高兴知道downvoter 的原因。 OP 提出问题,我试图帮助他。
      • 我更新了我的问题,但你没有更新你的答案。所以你的答案不再相关(实际上不是......也许评论会更好)。另外,现在你已经回答了,没有人再读这篇文章了......我仍然被困住了。请更新您的答案,我很乐意为它投票。
      猜你喜欢
      • 1970-01-01
      • 2015-07-21
      • 2012-12-11
      • 2014-08-17
      • 1970-01-01
      • 2016-06-19
      • 2021-01-17
      • 2020-07-08
      • 1970-01-01
      相关资源
      最近更新 更多