springboot整合FTP全盘扫描文件夹并下载

299 阅读3分钟

ftp上传的文件为先zip,再gz的文件。在将文件传送至s3的过程中,需要对第一层zip进行解压,保留第二层gz解压。默认的gz文件没有后缀名,在上传至s3时需要增加gz文件后缀名。 如果该文件从未上传至S3,则将该文件按照上一章节的要求解压缩,并上传至S3。上传成功后在数据库中记录。 如果数据库记录表明该文件已经上传过S3,则忽略

下载部分代码 控制层:

@PostMapping("/download")
public R download(){
    R download = ftpService.download();
    return download;
}

service层:

R download();

实现层:

public R download() {
    String fileName = null;
    //先获取该文件路径下所有的文件夹List
    List<String> fileNamePathList = FtpUtils.ftpListFiles(ftpConfig.getUrl(), ftpConfig.getPort(), ftpConfig.getUsername(),
            ftpConfig.getPassword(), ftpConfig.getRemotePath());
    // 拿到真正的文件
    List<String> fileNameList = new ArrayList<>();
    List<String> fileNames = new ArrayList<>();
    //遍历这些文件夹获取到所有文件名并拼接上
    for(String str : fileNamePathList){
        List<String> list = FtpUtils.ftpListFiles(ftpConfig.getUrl(), ftpConfig.getPort(), ftpConfig.getUsername(),
                ftpConfig.getPassword(), str);
        fileNameList.addAll(list);
    }
    // 截取文件名
    List<String> fileList = new ArrayList<>();
    for(String filePath : fileNameList){
        fileList.add(filePath.substring(filePath.lastIndexOf("/",filePath.lastIndexOf("/")-1)));
    }
    Iterator<String> iterator = fileNameList.iterator();
    Iterator<String> iterator1= fileList.iterator();
    while (iterator.hasNext()&&iterator1.hasNext()){
        String filePath= iterator.next();
        iterator1.next();
        fileName = filePath.substring(filePath.lastIndexOf("/")+1);
        String byFileName = userBillRepository.findByName(fileName);
        String remotePath = filePath.substring(0, filePath.lastIndexOf("/")+1);
        if(byFileName==null){
            boolean result = FtpUtils.ftpDownload(fileName, ftpConfig.getUrl(),ftpConfig.getPort(),ftpConfig.getUsername(),
                    ftpConfig.getPassword(), remotePath, ftpConfig.getDownDir());
            if (result) {
                UserBillEntity userBill = new UserBillEntity();
                userBill.setBillDate(fileName.substring(0,8));
                userBill.setFileName(fileName);
                fileNames.add(fileName);
                userBill.setIsUpload(0);
                userBill.setIsVerification(1);
                userBillRepository.save(userBill);
                log.info("=======下载文件"+ fileName +"成功=======");
            } else{
                log.info("=======下载文件"+ fileName +"失败=======");
                R.fail("下载文件失败");
            }
        }else {
            Integer isUpload = userBillRepository.findUpload(fileName);
            if(isUpload==0){
                try {
                    boolean result = FtpUtils.ftpDownload(fileName, ftpConfig.getUrl(),ftpConfig.getPort(),ftpConfig.getUsername(),
                            ftpConfig.getPassword(), remotePath, ftpConfig.getDownDir());
                } catch (Exception e) {
                    log.info("下载报错了....{}", e.getMessage());
                }
            }else{
                iterator1.remove();
            }
        }
    }
    R r = uploadFileService.findFile(ftpConfig.getDownDir(),ftpConfig.getRemotePath(),fileList,fileNames);

    return r;
}

工具类:

public class FtpUtils {
    private static FTPClient mFTPClient = new FTPClient();
    private static FtpUtils ftp = new FtpUtils();

    public FtpUtils() {
        // 在控制台打印操作过程
        mFTPClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
    }

    /**
     * 从ftp服务器下载文件到本地
     */
    public static boolean ftpDownload(String fileName, String ftpUrl, int ftpPort,
                                      String ftpUsername, String ftpPassword, String ftpRemotePath, String ftpDownDir) {
        boolean result = false;
        try {
            boolean isConnection = ftp.openConnection(ftpUrl, ftpPort, ftpUsername, ftpPassword);
            if (isConnection) {
                boolean isDownloadOk = ftp.downLoad(ftpRemotePath,ftpDownDir,fileName);
                boolean isCreateOk = ftp.createDirectory(ftpRemotePath, ftp.mFTPClient);
                if (isDownloadOk && isCreateOk) {
                    log.info("文件下载成功!");
                    result = true;
                } else {
                    log.info("文件下载失败!");
                    result = false;
                }
                ftp.logout();
            } else {
                log.info("链接ftp服务器失败,请检查配置信息是否正确!");
                result = false;
            }

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return result;

    }

    /**
     * 连接ftp服务器
     *
     * @param host
     *            ip地址
     * @param port
     *            端口号
     * @param account
     *            账号
     * @param pwd
     *            密码
     * @return 是否连接成功
     * @throws SocketException
     * @throws IOException
     */
    public boolean openConnection(String host, int port, String account, String pwd)
            throws SocketException, IOException {
        mFTPClient.setControlEncoding("UTF-8");
        mFTPClient.connect(host, port);

        if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
            mFTPClient.login(account, pwd);
            if (FTPReply.isPositiveCompletion(mFTPClient.getReplyCode())) {
                System.err.println(mFTPClient.getSystemType());
                FTPClientConfig config = new FTPClientConfig(mFTPClient.getSystemType().split(" ")[0]);
                //FTPClientConfig config = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
                config.setServerLanguageCode("zh");
                mFTPClient.configure(config);
                return true;
            }
        }
        disConnection();
        return false;
    }

    /**
     * 登出并断开连接
     */
    public void logout() {
        System.err.println("logout");
        if (mFTPClient.isConnected()) {
            System.err.println("logout");
            try {
                mFTPClient.logout();
                disConnection();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 断开连接
     */
    private void disConnection() {
        if (mFTPClient.isConnected()) {
            try {
                mFTPClient.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }


    /**
     * 下载文件到本地地址
     *
     * @param ftpRemotePath
     *            远程地址
     * @param localDir
     *            本地地址
     * @throws IOException
     */
    public boolean downLoad(String ftpRemotePath,String localDir,String filename) throws IOException {
        // 进入被动模式
        if(ftpRemotePath.endsWith("/")){
            ftpRemotePath=ftpRemotePath + filename;
        }else{
            ftpRemotePath=ftpRemotePath + "/"+ filename;
        }

      mFTPClient.enterLocalPassiveMode();
        // 以二进制进行传输数据
        mFTPClient.setFileType(FTP.ASCII_FILE_TYPE);
        FTPFile[] ftpFiles = mFTPClient.listFiles(ftpRemotePath);
        if (ftpFiles == null|| ftpFiles.length == 0) {
            log.info("远程文件不存在");
            return false;
        } else if (ftpFiles.length > 1) {
            log.info("远程文件是文件夹");
            return false;
        }
        long lRemoteSize = ftpFiles[0].getSize();
        // 本地文件的地址
        File localFileDir = new File(localDir);
        if (!localFileDir.exists()) {
            localFileDir.mkdirs();
        }
        File localFile = new File(localFileDir, ftpFiles[0].getName());
        long localSize = 0;
        FileOutputStream fos = null;
        if (localFile.exists()) {
            if (localFile.length() == lRemoteSize) {
                System.err.println("已经下载完毕");
                return true;
            } else if (localFile.length() < lRemoteSize) {
                // 传要下载的文件存在,进行断点续
                localSize = localFile.length();
                mFTPClient.setRestartOffset(localSize);
                fos = new FileOutputStream(localFile, true);
            }
        }
        if (fos == null) {
            fos = new FileOutputStream(localFile);
        }
        //此处必须添加编码集设置,否则可能会有is空指针的bug
        InputStream is = mFTPClient.retrieveFileStream(new String(ftpRemotePath.getBytes("UTF-8"), "ISO-8859-1"));
        byte[] buffers = new byte[1024];
        long step = lRemoteSize / 10;
        long process = localSize / step;
        int len = -1;
        while ((len = is.read(buffers)) != -1) {
            fos.write(buffers, 0, len);
            localSize += len;
            long newProcess = localSize / step;
            if (newProcess > process) {
                process = newProcess;
                System.err.println("下载进度:" + process);
            }
        }
        fos.close();
        is.close();
        boolean isDo = mFTPClient.completePendingCommand();
        if (isDo) {
            System.err.println("下载成功");
        } else {
            System.err.println("下载失败");
        }
        return isDo;
    }

  

     //接收ftp文件路径和路径下的所有文件夹或文件
    //拼接RemotePath路径+路径下的文件夹 或RemotePath+路径下文件夹+文件名
    public static List<String> getAllFilePath(String  ftpRemotePath, FTPFile[] ftpFiles){
        ArrayList<String> fileNameList = new ArrayList<>();
        for(int i=0; i<ftpFiles.length; i++){
            FTPFile ftpFile = ftpFiles[i];
            //endWith()方法判断传过来的路径底下是否还有文件夹
            //传来路径末尾是"/"表示路径下还有文件夹,否则表示已经精确到具体文件夹拼接具体文件名即可
            if(ftpRemotePath.endsWith("/")){
                fileNameList.add(ftpRemotePath + ftpFile.getName());
            }else{
                fileNameList.add(ftpRemotePath + "/" + ftpFile.getName());
            }

        }
        return fileNameList;
    }


    /**
     * 列举ftp服务器文件,根据ftp远程路径
     */
    public static  List<String> ftpListFiles(String ftpUrl, int ftpPort, String ftpUsername,String ftpPassword, String ftpRemotePath) {
        List<String> allFilename = new ArrayList<>();
        try {
            boolean isConnection = ftp.openConnection(ftpUrl, ftpPort, ftpUsername, ftpPassword);
            if (isConnection) {
                // 进入被动模式
                mFTPClient.enterLocalPassiveMode();
                //获取RemotePath路径下的所有文件夹或者文件
                FTPFile[] ftpFiles = mFTPClient.listFiles(ftpRemotePath);
                allFilename = getAllFilePath(ftpRemotePath, ftpFiles);
                ftp.logout();
            } else {
                log.info("连接ftp服务器失败,请检查配置信息是否正确!");
            }

        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return allFilename;

    }

    }
}