zoukankan      html  css  js  c++  java
  • Java实现连接FTP服务并传递文件

    public class FtpClientUtil {
    
        private String host;
    
        private int port;
    
        private String username;
    
        private String password;
    
        private int bufferSize = 10 * 1024 * 1024;
    
        private int soTimeout = 15000;
    
        private FTPClient ftp;
    
        public FTPClient getFtp() {
            return ftp;
        }
    
        public void setFtp(FTPClient ftp) {
            this.ftp = ftp;
        }
    
        private UploadStatus uploadStatus;
    
        public UploadStatus getUploadStatus() {
            return uploadStatus;
        }
    
        public void setUploadStatus(UploadStatus uploadStatus) {
            this.uploadStatus = uploadStatus;
        }
    
        public static class Builder {
            private String host;
            private int port = 21;
            private String username;
            private String password;
            private int bufferSize = 1024 * 1024;
            private FTPClientConfig config;
            private int defaultTimeout = 15000;
            private int connectTimeout = 15000;
            private int dataTimeout = 15000;
            private int controlKeepAliveTimeout = 300;
            private int soTimeout = 15000;
    
            public Builder() {
            }
    
            public Builder host(String host) {
                this.host = host;
                return this;
            }
    
            public Builder port(int port) {
                this.port = port;
                return this;
            }
    
            public Builder username(String username) {
                this.username = username;
                return this;
            }
    
            public Builder password(String password) {
                this.password = password;
                return this;
            }
    
            public Builder bufferSize(int bufferSize) {
                this.bufferSize = bufferSize;
                return this;
            }
    
            public Builder config(FTPClientConfig config) {
                this.config = config;
                return this;
            }
    
            public Builder defaultTimeout(int defaultTimeout) {
                this.defaultTimeout = defaultTimeout;
                return this;
            }
    
            public Builder connectTimeout(int connectTimeout) {
                this.connectTimeout = connectTimeout;
                return this;
            }
    
            public Builder dataTimeout(int dataTimeout) {
                this.dataTimeout = dataTimeout;
                return this;
            }
    
            public Builder soTimeout(int soTimeout) {
                this.soTimeout = soTimeout;
                return this;
            }
    
            public Builder controlKeepAliveTimeout(int controlKeepAliveTimeout) {
                this.controlKeepAliveTimeout = controlKeepAliveTimeout;
                return this;
            }
    
            public FtpClientUtil build() throws IOException {
                FtpClientUtil instance = new FtpClientUtil(this.host, this.port, this.username, this.password,
                        this.bufferSize, this.config, this.defaultTimeout, this.dataTimeout, this.connectTimeout,
                        this.controlKeepAliveTimeout, this.soTimeout);
                return instance;
            }
        }
    
        private FtpClientUtil(String host, int port, String username, String password, int bufferSize,
                FTPClientConfig config, int defaultTimeout, int dataTimeout, int connectTimeout,
                int controlKeepAliveTimeout, int soTimeout) throws IOException {
            this.host = host;
            this.port = port;
            this.username = username;
            this.password = password;
            this.bufferSize = bufferSize;
            this.soTimeout = soTimeout;
            this.ftp = new FTPClient();
            if (config != null) {
                this.ftp.configure(config);
            }
            ftp.setControlEncoding("UTF-8");
    //        ftp.setControlEncoding("GBK");
    //        ftp.setControlEncoding("gb2312");
            ftp.enterLocalPassiveMode();
            ftp.setDefaultTimeout(defaultTimeout);
            ftp.setConnectTimeout(connectTimeout);
            ftp.setDataTimeout(dataTimeout);
            // ftp.setSendDataSocketBufferSize(1024 * 256);
            if (this.bufferSize > 0) {
                ftp.setBufferSize(this.bufferSize);
            }
    
            // keeping the control connection alive
            ftp.setControlKeepAliveTimeout(controlKeepAliveTimeout);// 每大约5分钟发一次noop,防止大文件传输导致的控制连接中断
        }
    
        public FtpClientUtil connect() throws SocketException, IOException {
            if (!this.ftp.isConnected()) {
                this.ftp.connect(this.host, this.port);
                int reply = this.ftp.getReplyCode();
                if (!FTPReply.isPositiveCompletion(reply)) {
                    logger.warn("ftp服务器返回码[{}], 连接失败...", reply);
                    throw new IllegalStateException("连接ftp服务器失败,返回的状态码是" + reply);
                }
            }
            this.ftp.setSoTimeout(this.soTimeout);
            return this;
        }
    
        public FtpClientUtil login() throws IOException {
            boolean suc = this.ftp.login(this.username, this.password);
            if (!suc) {
                throw new IllegalStateException("登录ftp服务器失败");
            }
            return this;
        }
    
        /**
         * ftp上传文件功能
         * 
         * @param file
         *            要上传的文件
         * @param relativePath
         *            要上传到ftp服务器的相对路径
         * @return
         * @throws IOException
         */
        public FtpClientUtil upload(File file, String relativePath) throws IOException {
            FileInputStream fInputStream = new FileInputStream(file);
            return this.upload(fInputStream, file.getName(), relativePath, file.length());
        }
    
        public FtpClientUtil upload(InputStream inputStream, String name, String relativePath, long localSize)
                throws IOException {
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            changeWorkingDirectory(relativePath);
    
            this.ftp.enterLocalPassiveMode();
            FTPFile[] listFiles = this.ftp.listFiles(name);
            // long localSize = inputStream.available();// ? 不知道好用否
            if (listFiles.length == 1) {
                long remoteSize = listFiles[0].getSize();
    
                if (remoteSize == localSize) {
                    this.setUploadStatus(UploadStatus.File_Exits);
                    return this;
                } else if (remoteSize > localSize) {
                    this.setUploadStatus(UploadStatus.Remote_Bigger_Local);
                    return this;
                }
                this.uploadFile(inputStream, name, remoteSize, localSize);
            } else {
                this.uploadFile(inputStream, name, 0, localSize);
            }
            logger.info("{}/{} upload success", relativePath, name);
            return this;
        }
    
        private void uploadFile(InputStream inputStream, String name, long remoteSize, long localSize) throws IOException {
            this.ftp.enterLocalPassiveMode();
            OutputStream output = null;
            long step = localSize / 100;
            long process = 0;
            long localreadbytes = 0L;
            try {
                if (remoteSize > 0) {
                    output = this.ftp.appendFileStream(name);
                    this.ftp.setRestartOffset(remoteSize);
                    inputStream.skip(remoteSize);
                    process = remoteSize / step;
                    localreadbytes = remoteSize;
                } else {
                    output = this.ftp.storeFileStream(name);
                }
                byte[] bytes = new byte[1024];
                int c;
                while ((c = inputStream.read(bytes)) != -1) {
                    output.write(bytes, 0, c);
                    localreadbytes += c;
                    if (localreadbytes / step >= process + 10) {
                        process = localreadbytes / step;
                        logger.info("文件【" + name + "】上传ftp进度汇报, process = " + process);
                    }
                }
                logger.info("文件" + name + "上传ftp进度汇报, process = " + 100);
                output.flush();
                inputStream.close();
                output.close();
                boolean result = this.ftp.completePendingCommand();
                if (remoteSize > 0) {
                    this.setUploadStatus(
                            result ? UploadStatus.Upload_From_Break_Success : UploadStatus.Upload_From_Break_Failed);
                } else {
                    this.setUploadStatus(
                            result ? UploadStatus.Upload_New_File_Success : UploadStatus.Upload_New_File_Failed);
                }
            } catch (Exception e) {
                this.setUploadStatus(
                        remoteSize > 0 ? UploadStatus.Upload_From_Break_Failed : UploadStatus.Upload_New_File_Failed);
            }
    
        }
    
        public OutputStream upload(String name, String relativePath) throws IOException {
            ftp.setFileType(FTP.BINARY_FILE_TYPE);
            changeWorkingDirectory(relativePath);
            ftp.enterLocalPassiveMode();
            return this.ftp.storeFileStream(name);
        }
    
        public void changeWorkingDirectory(String relativePath) throws IOException {
            if (relativePath == null) {
                throw new NullPointerException("relativePath can't be null");
            }
            String[] dirs = relativePath.split("/");
            for (String dir : dirs) {
                if (!this.ftp.changeWorkingDirectory(dir)) {
                    if (this.ftp.makeDirectory(dir)) {
                        this.ftp.changeWorkingDirectory(dir);
                    } else {
                        logger.warn("{}目录创建失败, 导致不能进入合适的目录进行上传", dir);
                    }
                }
            }
        }
    
        /**
         * ftp上传目录下所有文件的功能
         * 
         * @param file
         *            要上传的目录
         * @param relativePath
         *            要上传到ftp服务器的相对路径
         * @return
         * @throws IOException
         */
        public FtpClientUtil uploadDir(File file, String relativePath) throws IOException {
            if (!file.isDirectory()) {
                throw new IllegalArgumentException("file argument is not a directory!");
            }
            relativePath = relativePath + "/" + file.getName();
            File[] listFiles = file.listFiles();
            for (File f : listFiles) {
                this.uploadFree(f, relativePath);
            }
            return this;
        }
    
        /**
         * ftp上传文件, 调用方不用区分文件是否为目录,由该方法自己区分处理
         * 
         * @param file
         *            要上传的文件
         * @param relativePath
         *            要上传到ftp服务器的相对路径
         * @return
         * @throws IOException
         */
        public FtpClientUtil uploadFree(File file, String relativePath) throws IOException {
            if (file.isDirectory()) {
                this.uploadDir(file, relativePath);
            } else {
                this.upload(file, relativePath);
            }
            return this;
        }
    
        /**
         * 本方法是上传的快捷方法,方法中自身包含了ftp 连接、登陆、上传、退出、断开各个步骤
         * 
         * @param file
         *            要上传的文件
         * @param relativePath
         *            要上传到ftp服务器的相对路径
         */
        public boolean uploadOneStep(File file, String relativePath) {
            try {
                this.connect().login().uploadFree(file, relativePath);
                return true;
            } catch (IOException e) {
                String msg = String.format("ftp上传时发生异常, filename = [%s], relativePath = [%s]", file.getName(),
                        relativePath);
                logger.error(msg, e);
                return false;
            } finally {
                this.disconnectFinally();
            }
        }
    
        public boolean uploadOneStepForStream(InputStream inputStram, String name, String relativePath, long localSize) {
            try {
                this.connect().login().upload(inputStram, name, relativePath, localSize);
                return true;
            } catch (IOException e) {
                String msg = String.format("ftp上传时发生异常, filename = [%s], relativePath = [%s]", name, relativePath);
                logger.error(msg, e);
                return false;
            } finally {
                this.disconnectFinally();
            }
        }
    
        public interface OutputStreamForUpload {
            public void write(OutputStream outputStream) throws IOException;
        }
    
        public boolean uploadOneStepForStream(OutputStreamForUpload outputUpload, String name, String relativePath) {
            try {
                this.connect().login();
                OutputStream upload = this.upload(name, relativePath);
                outputUpload.write(upload);
                return true;
            } catch (IOException e) {
                String msg = String.format("ftp上传时发生异常, filename = [%s], relativePath = [%s]", name, relativePath);
                logger.error(msg, e);
                return false;
            } finally {
                this.disconnectFinally();
            }
        }
    
        public FtpClientUtil logout() throws IOException {
            this.ftp.logout();
            return this;
        }
    
        public void disconnect() {
            this.disconnectFinally();
        }
    
        private void disconnectFinally() {
            if (this.ftp.isConnected()) {
                try {
                    this.ftp.disconnect();
                } catch (IOException ioe) {
                    logger.warn("ftp断开服务器链接异常", ioe);
                }
            }
        }
    
        @Override
        public String toString() {
            return "FtpClientHelper [host=" + host + ", port=" + port + ", username=" + username + ", password=" + password
                    + "]";
        }
    
    }

    看代码吧:

  • 相关阅读:
    前端规范标准(一)
    node之旅(3) Express之我的第一个应用
    node之旅(2) hello wrold!
    node之旅(1) 安装NodeJS
    CSS3 基础知识
    博客转移公告
    博客主题更换留念
    网络流-费用流zkw算法
    网络流-最大流ISAP
    字符串总结-三大“自动机”
  • 原文地址:https://www.cnblogs.com/liangblog/p/8890258.html
Copyright © 2011-2022 走看看