美文网首页
java使用FTP

java使用FTP

作者: 好多个胖子 | 来源:发表于2019-08-10 14:39 被阅读0次

    引入第三方java库

    //gradle形式引入
      implementation 'commons-net:commons-net:3.6'
    
    //maven
    <!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
    <dependency>
        <groupId>commons-net</groupId>
        <artifactId>commons-net</artifactId>
        <version>3.6</version>
    </dependency>
    

    主要api介绍

    //连接
     ftpClient.connect(hostName, port);
     
    //登录
     ftpClient.login(username, password);
     
    //列出指定目录下的文件 
    ftpClient.listFiles(remotePath);
    
    // 上传文件
    ftpClient.storeFile(remotePath, inputstream); 
    
    //采用流的方式上传文件
    ftpClient.storeFileStream(remotePath);
    
    //下载文件
    ftpClient.retrieveFile(filename, outputStream);  
    
    //流方式下载文件
    ftpClient.retrieveFileStream(filename);
    
    // ftpClient命令执行的回调   ftpClient所有的操作都是通过执行服务器命令来完成的,可通过该方式回调命令的执行
     ftpClient.addProtocolCommandListener(new ProtocolCommandListener(){});
     
     
     //命令操作, 
     //可执行的命令封装在  FTPCmd  枚举类中,
     //操作CWD是  cd ..   的意思,也就是回到上层目录
      ftpClient.doCommand(FTPCmd.CWD.getCommand(), "..");
    
    

    初始化 连接到服务器

    连接操作需要四个参数,分别是服务器ip,端口,用户名,密码

     protected final boolean openConnect() {
            if (ftpClient == null) {
                ftpClient = new FTPClient();
            }
            if (ftpClient.isConnected()) {
                return true;
            }
            // 中文转码
            ftpClient.setControlEncoding("UTF-8");
            int reply; 
            // 连接至服务器
            try {
                ftpClient.connect(hostName, port);
            } catch (IOException e) {
                onError("connect io error:" + e.getMessage());
                return false;
            }
            // 获取响应值
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                onError("connect fail: " + reply);
                return false;
            }
            // 登录到服务器
            try {
                ftpClient.login(username, password);
            } catch (IOException e) {
                onError("login io error: " + e.getMessage());
                return false;
            }
    
            // 获取响应值
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                onError("login fail: " + reply);
                return false;
            }
    
            // 获取登录信息
            try {
                FTPClientConfig config = new FTPClientConfig(ftpClient.getSystemType().split(" ")[0]);
                config.setServerLanguageCode("zh");
                ftpClient.configure(config);
                // 使用被动模式设为默认
                ftpClient.enterLocalPassiveMode();
                // 二进制文件支持
                ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
                // 设置模式
                ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
            } catch (IOException e) {
                onError("config io error: " + e.getMessage());
                return false;
            }
    
            return true;
    

    文件上传

    文件上传分为文件上传和文件夹上传,多文件上传需要注意每次递归到内层工作目录做上传之后,应该恢复到上层目录 ,下载文件也一样

    • ftpClient.storeFile(remotePath, inputstream); 这种方式不能回调进度

    • ftpClient.storeFileStream(remotePath); 打开一个输出流用于写入到服务器,这种方式可以回调上传进度

     /**
         * 上传. 流的方式
         *
         * @param localFile  本地文件
         * @param remotePath FTP目录
         * @return Result
         * @throws IOException
         */
        public void upload(File localFile, String remotePath, IFtpListener listener) {
            setExecuteListener(listener);
            if (!openConnect()) {
                return;
            }
            // 改变FTP目录
            try {
                ftpClient.changeWorkingDirectory(remotePath);
                // 获取上传前时间
                if (localFile.isDirectory()) {
                    // 上传多个文件
                    uploadMany(localFile);
                } else {
                    // 上传单个文件
                    uploadSingle(localFile);
                }
            } catch (IOException e) {
                onError("upload: changeWorkingDirectory error");
                return;
            }
            closeConnect();
        }
        
        
        /**
         * 上传单个文件.
         *
         * @param localFile 本地文件
         */
        protected void uploadSingle(File localFile) throws IOException {
            final long totalSize = localFile.length();
            final String filename = localFile.getName();
            //开始
            onStart(filename);
    
            InputStream inputStream = new FileInputStream(localFile);
            OutputStream outputStream = ftpClient.storeFileStream(filename);
    
            //从输入流写入到输出流
            ioExecutor(filename, inputStream, outputStream, totalSize);
            //结束
            onComplete(filename);
        }
    
        /**
         * 上传多个文件.
         *
         * @param localFile 本地文件夹
         */
        protected void uploadMany(@NotNull File localFile) throws IOException {
            if (!localFile.exists()) {
                onError("本地文件不存在: " + localFile.getAbsolutePath());
                return;
            }
            // FTP下创建文件夹
            final String childDir = localFile.getName();
            ftpClient.makeDirectory(childDir);
            // 更改FTP目录
            ftpClient.changeWorkingDirectory(childDir);
            // 得到当前目录下所有文件
            File[] files = localFile.listFiles();
            if (files == null) {
                onComplete(childDir);
                return;
            }
            // 遍历得到每个文件并上传
            for (File file : files) {
                if (file.isHidden()) {
                    continue;
                }
                if (file.isDirectory()) {
                    // 上传多个文件
                    uploadMany(file);
                    //切回到原来的目录 该操作是关键
                    ftpClient.doCommand(FTPCmd.CWD.getCommand(), "..");
                } else {
                    // 上传单个文件
                    uploadSingle(file);
                }
            }
        }
    
    

    文件下载

    文件下载分为单文件下载和文件夹下载,多文件上传需要注意每次递归到内层工作目录做上传之后,应该恢复到上层目录 ,下载文件也一样

    • ftpClient.retrieveFile(filename, outputStream); 这种方式不能回调进度

    • ftpClient.retrieveFileStream(filename); 打开一个输入流 读取服务器文件,这种方式可以回调上传进度

     /**
         * 下载.
         *
         * @param remotePath FTP目录
         * @param fileName   文件名
         * @param localPath  本地目录
         * @return Result
         * @throws IOException
         */
        public void download(String remotePath, String fileName, String localPath, IFtpListener listener) {
            setExecuteListener(listener);
            if (!openConnect()) {
                return;
            }
            // 改变FTP目录
            try {
                ftpClient.changeWorkingDirectory(remotePath);
    
                // 得到FTP当前目录下所有文件
                FTPFile[] ftpFiles = ftpClient.listFiles();
    
                // 循环遍历
                FTPFile targetFile = null;
                for (FTPFile ftpFile : ftpFiles) {
                    // 找到需要下载的文件
                    if (ftpFile.getName().equals(fileName)) {
                        targetFile = ftpFile;
                        break;
                    }
                }
                if (targetFile == null) {
                    onError("服务端文件不存在:" + remotePath + "/" + fileName);
                    return;
                }
                // 创建本地目录
                File file = new File(localPath + "/" + fileName);
                if (targetFile.isDirectory()) {
                    // 下载多个文件
                    downloadMany(file, targetFile);
                } else {
                    // 下载当个文件
                    downloadSingle(file, targetFile);
                }
            } catch (IOException e) {
                onError("download:  " + e.getMessage());
            }
            // 下载完时间
            closeConnect();
        }
        
         /**
         * 下载单个文件.
         *
         * @param localFile 本地目录
         * @param ftpFile   FTP目录
         */
        protected void downloadSingle(File localFile, FTPFile ftpFile) throws IOException {
            //文件总大小
            final long totalSize = ftpFile.getSize();
            final String filename = ftpFile.getName();
            //开始
            onStart(filename);
            // 创建输出流
            OutputStream outputStream = new FileOutputStream(localFile);
            ftpClient.retrieveFile(filename, outputStream);
            InputStream inputStream = ftpClient.retrieveFileStream(filename);
    
            //从输入流写入到输出流  并打印进度
            ioExecutor(filename, inputStream, outputStream, totalSize);
    
            //结束
            onComplete(filename);
        }
    
        /**
         * 下载多个文件.
         *
         * @param remoteFile 要下载的远程文件夹
         */
        protected void downloadMany(File localFile, FTPFile remoteFile) throws IOException {
            // 创建本地文件夹
            if (!localFile.exists()) {
                if (!localFile.mkdirs()) {
                    onError("创建本地文件失败: " + localFile.getAbsolutePath());
                    return;
                }
            }
            // 更改FTP当前目录
            ftpClient.changeWorkingDirectory(remoteFile.getName());
            // 得到FTP当前目录下所有文件
            FTPFile[] ftpFiles = ftpClient.listFiles();
            // 循环遍历
            for (FTPFile ftpFile : ftpFiles) {
                // 创建文件
                File file = new File(localFile.getAbsolutePath() + "/" + ftpFile.getName());
                if (ftpFile.isDirectory()) {
                    // 下载多个文件
                    downloadMany(file, ftpFile);
                    // 返回到外层目录
                    ftpClient.doCommand(FTPCmd.CWD.getCommand(), "..");
                } else {
                    // 下载单个文件
                    downloadSingle(file, ftpFile);
                }
            }
        }
    

    相关文章

      网友评论

          本文标题:java使用FTP

          本文链接:https://www.haomeiwen.com/subject/sjdrjctx.html