ftpClient.retrieveFileStream导致FTPClient后面操作失败

public BufferedInputStream getFileInputStream(String filePath) {
        BufferedInputStream is = null;
        try {
            logger.debug("FtpUtils->getFileInputStream->FTP开始下载文件!");
            FTPFile ftpFile = ftpClient.mlistFile(filePath);
            if (null != ftpFile) {
                is = new BufferedInputStream(ftpClient.retrieveFileStream(filePath));
            } else {
                throw new BaseException("FtpUtils->getFileInputStream->找不到文件!");
            }
            logger.debug("FtpUtils->getFileInputStream->FTP下载文件成功!");
        } catch (Exception e) {
            e.printStackTrace();
        }
        return is;
    }

执行retrieveFileStream后执行FTPClient后面的操作如changeWorkingDirectory、listFiles会失败,在Debug时使用静态方法测试调用listFiles时出现以下错误,但程序正常运行时没有抛出异常,

java.io.IOException: Unable to determine system type - response: 451 Another command is currently pending, please try again later.
	at org.apache.commons.net.ftp.FTPClient.getSystemType(FTPClient.java:2801)
	at org.apache.commons.net.ftp.FTPClient.__createParser(FTPClient.java:3369)
	at org.apache.commons.net.ftp.FTPClient.initiateListParsing(FTPClient.java:3338)
	at org.apache.commons.net.ftp.FTPClient.listFiles(FTPClient.java:3016)

 

原因:读完InputStream后必须在关闭它,如果不这样做,不关闭后续命令可能会意外地执行。要完成文件传输,必须调用completePendingCommand completePendingCommand和检查其返回值以验证是否成功。如果不这样做,后续命令可能会意外地执行。retrieveFileStream注释如下:
/**
     * Returns an InputStream from which a named file from the server
     * can be read.  If the current file type is ASCII, the returned
     * InputStream will convert line separators in the file to
     * the local representation.  You must close the InputStream when you
     * finish reading from it.  The InputStream itself will take care of
     * closing the parent data connection socket upon being closed.
     * <p>
     * <b>To finalize the file transfer you must call
     * {@link #completePendingCommand  completePendingCommand } and
     * check its return value to verify success.</b>
     * If this is not done, subsequent commands may behave unexpectedly.
     * <p>
     * Note: if you have used {@link #setRestartOffset(long)},
     * the file data will start from the selected offset.
     *
     * @param remote  The name of the remote file.
     * @return An InputStream from which the remote file can be read.  If
     *      the data connection cannot be opened (e.g., the file does not
     *      exist), null is returned (in which case you may check the reply
     *      code to determine the exact reason for failure).
     * @throws FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public InputStream retrieveFileStream(String remote) throws IOException
    {
        return _retrieveFileStream(FTPCmd.RETR.getCommand(), remote);
    }

 /**
     * There are a few FTPClient methods that do not complete the
     * entire sequence of FTP commands to complete a transaction.  These
     * commands require some action by the programmer after the reception
     * of a positive intermediate command.  After the programmer's code
     * completes its actions, it must call this method to receive
     * the completion reply from the server and verify the success of the
     * entire transaction.
     * <p>
     * For example,
     * <pre>
     * InputStream input;
     * OutputStream output;
     * input  = new FileInputStream("foobaz.txt");
     * output = ftp.storeFileStream("foobar.txt")
     * if(!FTPReply.isPositiveIntermediate(ftp.getReplyCode())) {
     *     input.close();
     *     output.close();
     *     ftp.logout();
     *     ftp.disconnect();
     *     System.err.println("File transfer failed.");
     *     System.exit(1);
     * }
     * Util.copyStream(input, output);
     * input.close();
     * output.close();
     * // Must call completePendingCommand() to finish command.
     * if(!ftp.completePendingCommand()) {
     *     ftp.logout();
     *     ftp.disconnect();
     *     System.err.println("File transfer failed.");
     *     System.exit(1);
     * }
     * </pre>
     *
     * @return True if successfully completed, false if not.
     * @throws FTPConnectionClosedException
     *      If the FTP server prematurely closes the connection as a result
     *      of the client being idle or some other reason causing the server
     *      to send FTP reply code 421.  This exception may be caught either
     *      as an IOException or independently as itself.
     * @throws IOException  If an I/O error occurs while either sending a
     *      command to the server or receiving a reply from the server.
     */
    public boolean completePendingCommand() throws IOException
    {
        return FTPReply.isPositiveCompletion(getReply());
    }

解决方案:关闭流,调用completePendingCommand()方法

InputStream in = ftpClient.retrieveFileStream(fileName);
in.close();
ftpClient.completePendingCommand();

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值