文件管理存储之FTP存储

package com.guige.base.fileutils;


import com.alibaba.fastjson.annotation.JSONField;
import com.guige.base.dto.FileBaseDto;
import org.apache.commons.net.PrintCommandListener;
import org.apache.commons.net.ftp.*;

import java.io.*;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;

public class FtpFileUtil extends FileUtil {
    @JSONField(serialize=false)
    private final FTPClient ftp =new FTPClient();
    private String hostname;
    private Integer port;
    private String username;
    private String password;

    private int connectCount = 0;
    private String workPath;
    public FtpFileUtil(String hostname, Integer port, String username, String password) {
        this.hostname = hostname;
        this.port = port;
        this.username = username;
        this.password = password;
        super.getLinkConf().put("HOSTNAME",hostname);
        super.getLinkConf().put("PORT",port+"");
        super.getLinkConf().put("USERNAME",username);
        super.getLinkConf().put("PASSWORD",password);
        this.ftp.setControlEncoding("UTF-8");

    }

    public int getConnectCount() {
        return connectCount;
    }

    public void setConnectCount(int connectCount) {
        this.connectCount = connectCount;
    }

    /**
     * 连接
     *
     * @return
     * @throws IOException
     */
    private boolean connect() throws IOException {
        if (this.ftp.isConnected()) {
            setConnectCount(getConnectCount() + 1);
//           log.info(getConnectCount()+"添加链接 不创建");
            this.ftp.changeWorkingDirectory(workPath);
            return true;
        }
        boolean debug = false;
        if (debug) {
            // 设置将过程中使用到的命令输出到控制台
            this.ftp.addProtocolCommandListener(new PrintCommandListener(
                    new PrintWriter(System.out), true));
        }
        //设置系统类型
        final FTPClientConfig config = new FTPClientConfig(
                FTPClientConfig.SYST_UNIX);
        this.ftp.configure(config);
        try {
            this.ftp.connect(hostname, port);
            if (!FTPReply.isPositiveCompletion(this.ftp.getReplyCode())) {
                this.ftp.disconnect();
                throw new IOException("FTP server refused connection.");

            }
        } catch (IOException e) {
            if (this.ftp.isConnected()) {
                try {
                    this.ftp.disconnect();
                } catch (IOException f) {
                    throw new IOException("FTP server refused connection.");
                }
            }

            e.printStackTrace();
            throw new IOException("FTP server refused connection.");
        }
        if (!this.ftp.login(username, password)) {
            this.ftp.logout();
            throw new IOException("Could not login to server.");
        }
        setConnectCount(getConnectCount() + 1);
      // log.info(getConnectCount()+"创建链接");
        workPath=this.ftp.printWorkingDirectory();
        return true;
    }

    /**
     * 销毁
     *
     * @throws IOException
     */
    private void disconnect() throws IOException {
        if (this.ftp.isConnected()) {
            try {
                if (getConnectCount()-1>=1) {
                    //在链接内部  不关闭
                    setConnectCount(getConnectCount() - 1);
                 //  log.info(getConnectCount()+"在链接内部  不关闭");
                } else {
                    this.ftp.logout();
                    this.ftp.disconnect();
                    setConnectCount(getConnectCount() - 1);
                  //  log.info(getConnectCount()+"关闭FTP链接");
                }

            } catch (IOException f) {
            }
        }
    }

    /**
     * 在FTP服务器上创建并转到工作目录
     *
     * @param relativePath 相对工作路径,不包含文件名:如 dd/11/22/33
     * @param ftpClient    录创建是否成功
     * @return
     * @throws IOException
     */
    private boolean createDirectory(String relativePath, FTPClient ftpClient)
            throws IOException {
      /*  if (!relativePath.startsWith("/")) {
            relativePath = "/" + relativePath;
        }*/
        if (!changeWorkingDirectory(relativePath)) {
            //目录不存在,则创建各级目录
            for (String subDir : relativePath.split("/")) {
                if (!subDir.equals("")) {
                    String newDir = ftpClient.printWorkingDirectory() + "/"
                            + subDir;
                    ftpClient.mkd(newDir);
                    if (!changeWorkingDirectory(newDir)) {
                        return false;
                    }
                }
            }
        }
        return true;
    }

    @Override
    public boolean saveFile(String pathStr, String filename, InputStream input, boolean replace_existing) throws IOException {
        try {
           connect();



            String path = Paths.get(pathStr).toString();
            String workPath = this.ftp.printWorkingDirectory();
            // 创建并转到工作目录
            String absDstDir =  path.replace("\\","/");

            createDirectory(absDstDir, this.ftp);
            // 设置各种属性
            this.ftp.setFileType(FTP.BINARY_FILE_TYPE);
            // Use passive mode as default because most of us are behind firewalls these days.
            this.ftp.enterLocalPassiveMode();

            this.ftp.setBufferSize(1024);
            // 进度监听
            FTPFile[] files = this.ftp.listFiles(filename);

            if (files.length == 1) {
                if (replace_existing) {
                    if (this.ftp.deleteFile(filename)) {
                        this.ftp.storeFile(filename, input);
                        input.close();
                    } else {
                        throw new IOException("文件已存在 删除失败");
                    }
                } else {
                    throw new IOException("文件已存在");
                }

            } else {

                this.ftp.storeFile(filename, input);
                input.close();
            }

        } finally {

            disconnect();
        }
        return true;
    }

    @Override
    public boolean saveFile(String path, String filename, byte[] fileDate, boolean replace_existing) throws IOException {
        InputStream input = new ByteArrayInputStream(fileDate);
        return saveFile(path, filename, input, replace_existing);
    }

    @Override
    public boolean saveFile(String path, String filename, String base64Data, boolean replace_existing) throws IOException {
        byte[] fileDate = com.sun.org.apache.xerces.internal.impl.dv.util.Base64.decode(base64Data);
        return saveFile(path, filename, fileDate, replace_existing);
    }

    @Override
    public boolean saveFile(String path, String filename, File file, boolean replace_existing) throws IOException {
        InputStream input = new FileInputStream(file);
        return saveFile(path, filename, input, replace_existing);
    }

    @Override
    public boolean saveFile(String path, File file, boolean replace_existing) throws IOException {
        InputStream input = new FileInputStream(file);
        return saveFile(path, file.getName(), input, replace_existing);
    }

    @Override
    public boolean saveFile(String path, List<File> files, boolean replace_existing) throws IOException {
        try {
            connect();
            for (File file : files) {
                saveFile(path, file, replace_existing);
            }
        }finally {
            disconnect();
        }

        return true;
    }

    @Override
    public boolean saveLocalFile(String path, List<String> urls, boolean replace_existing) throws IOException {
        try {
         //  log.info("---开启");
            connect();
            for (String url : urls) {
                saveFile(path, new File(url), replace_existing);
            }
        }finally {
         //  log.info("---关闭");
            disconnect();
        }

        return true;

    }

    @Override
    public InputStream readInputStream(String pathStr, String filename) throws IOException {
        try {
            connect();
            this.ftp.enterLocalPassiveMode();
            if (!changeWorkingDirectory(pathStr)) {
                return null;
            }else{
                return this.ftp.retrieveFileStream(filename);
            }

        } catch (Exception e) {
            e.printStackTrace();
            throw new IOException("下载失败." + e.getMessage());
        } finally {
            disconnect();
        }
    }

    @Override
    public List<FileBaseDto> readFileList(String pathStr, boolean isReadDir) throws IOException {
        List<FileBaseDto> list = new ArrayList<>();
        try {
            connect();
            pathStr = Paths.get(pathStr).toString();
            pathStr.replace("\\", "/");
             list.addAll(readFileList(pathStr, isReadDir, this.ftp));
            System.out.println(list.size());
            return list;
        } catch (Exception e){
            e.printStackTrace();

        }finally {
            System.out.println(list.size());
            disconnect();
        }
        return list;
    }

    @Override
    public FileBaseDto readFileInfo(String path, String filename) throws IOException {
        FileBaseDto fileBaseDto = null;
        try {
            connect();
          String  pathStr = Paths.get(path,filename).toString();
            pathStr.replace("\\", "/");
            List<FileBaseDto> list =  readFileList(pathStr, false, this.ftp);
            if(list !=null&&list.size()!=0){
                fileBaseDto= list.get(0);
            }

        } finally {
            disconnect();
        }
        return fileBaseDto;
    }


    private List<FileBaseDto> readFileList(String pathStr, boolean isReadDir, FTPClient ftpClient) throws IOException {
        List<FileBaseDto> fileBaseDtos = new ArrayList<>();
        try {
            connect();
            // Use passive mode as default because most of us are behind firewalls these days.
            this.ftp.enterLocalPassiveMode();
            Path path = Paths.get(pathStr);
            Path filePath = null;
            if (pathStr.contains(".")) {
                filePath = path.getParent();
            } else {
                filePath = path;
            }
            if (!changeWorkingDirectory(filePath.toString())) {
               return fileBaseDtos;
            } else {
                FTPFile[] files = null;
                if (pathStr.contains(".")) {
                    files = ftpClient.listFiles(path.getFileName().toString());
                } else {
                    files = ftpClient.listFiles();
                }
                if (files != null && files.length > 0) {
                    for (FTPFile ftpFile : files) {
                        FileBaseDto fileBaseDto = new FileBaseDto();
                        fileBaseDto.setContentType(getContentType(ftpFile.getName().toString()));
                        fileBaseDto.setOriginName(ftpFile.getName().toString());
                        fileBaseDto.setFilePath(filePath.toString());
                        fileBaseDto.setFileSize(ftpFile.getSize());
                        fileBaseDto.setStorageType(2);
                        if (ftpFile.isFile()) {
                            fileBaseDtos.add(fileBaseDto);
                        } else if (ftpFile.isDirectory()) {
                            if (isReadDir) {
                                fileBaseDtos.add(fileBaseDto);
                            }
                                fileBaseDtos.addAll(readFileList(filePath.resolve(ftpFile.getName()).toString(), isReadDir,ftpClient));

                        }
                    }
                }

            }
        } catch (Exception e) {
            e.printStackTrace();
            throw new IOException( e.getMessage());
        } finally {
            disconnect();
        }
        return fileBaseDtos;
    }


    @Override
    public boolean delete(String pathName) throws IOException {
        try {
            connect();
            if(!pathName.contains(workPath)) {
                pathName = Paths.get(workPath, pathName).toString();
            }
            pathName = pathName.replace("\\", "/");
            if(pathName.contains(".")){
                if (!ftp.deleteFile(pathName)){
                    return false;
                }else{
                    return true;
                }
            }

            List<FileBaseDto> list =  readFileList(pathName, true);
            if(list.size()<1){
                return false;
            }
            for(FileBaseDto fileBaseDto:list){
                if(fileBaseDto.getContentType().equals("dir")){
                   delete(fileBaseDto.getFilePath());
                }else{
                    ftp.deleteFile(Paths.get(fileBaseDto.getFilePath(),fileBaseDto.getOriginName()).toString().replace("\\","/"));
                }
            }
            // 切换到父目录,不然删不掉文件夹
            changeWorkingDirectory(Paths.get(pathName).getParent().toString().replace("\\","/"));
            ftp.removeDirectory(pathName);
        }catch (Exception e){
            e.printStackTrace();
            throw new IOException("删除失败"+e.getMessage());
        }finally {
            disconnect();
        }
        return true;
    }

    @Override
    public boolean delete(List<String> paths) throws IOException {
        try {
            connect();
            for (String path : paths) {
                try {
                    delete(path);
                }catch (Exception e){
                    e.printStackTrace();

                }
            }
        }catch (Exception e){
            e.printStackTrace();
            throw new IOException("删除失败"+e.getMessage());
        }finally {
            disconnect();
        }
        return true;

    }

    @Override
    public boolean exists(String path) throws IOException {
        try {
            List<FileBaseDto> list = readFileList(path, true);
            if (list != null && list.size() > 0) {
                return true;
            }
            return false;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }

    @Override
    public boolean moveTo(String path, String newPath, boolean replace_existing) throws IOException {
        try {
            connect();
            path=Paths.get(path).toString().replace("\\","/");
            newPath=Paths.get(newPath).toString().replace("\\","/");
            operateDir(true,path,newPath,replace_existing);
        }catch (Exception e){
            e.printStackTrace();
            throw new IOException(e.getMessage());
        }finally {
            disconnect();
        }
        return true;
    }

    @Override
    public boolean copy(String path, String newPath, boolean replace_existing) throws IOException {
        throw  new IOException("复制失败,FTP未实现复制功能,可先下载再上传到其他目录");
    }
    private void operateDir(boolean move, String path, String newPath, boolean replace_existing) throws IOException {


        if (path.contains(".") && !newPath.contains(".")) {
            throw new IllegalArgumentException("源文件是文件,目标文件是文件夹");
        } else if (!path.contains(".") && newPath.contains(".")) {
            throw new IllegalArgumentException("目标文件是文件,源文件是文件夹");
        }
        if (newPath.contains(path)) {
            throw new IllegalArgumentException("目标文件夹不能是源文件夹的子文件夹");
        }
        if(move){
            if(!this.ftp.rename(path,newPath)){
                //检查文件是否存在
                if(exists(newPath)){
                    if(replace_existing){
                        delete(newPath);
                        if(exists(newPath)){
                            delete(newPath);
                        }
                        if(!exists(newPath)){
                            if(!this.ftp.rename(path,newPath)){
                                throw  new IOException("移动失败,该文件不能覆盖");
                            }
                        }else{
                            throw  new IOException("移动失败,该文件不能覆盖");
                        }

                    }else{
                        throw  new IOException("移动失败,该文件已存在");
                    }
                }
            }
            return;
        }else{
            throw  new IOException("复制失败,FTP未实现复制功能,可先下载再上传到其他目录");
        }

    }


    /**
     * 复制文件夹.
     *
     * @param sourceDir
     * @param targetDir
     * @throws IOException
     */
    public void copyDirectiory(String sourceDir, String targetDir,FTPClient ftpClient) throws IOException {
        // 新建目标目录
        if (!exists(targetDir)) {
            createDirectory(targetDir,ftpClient);
        }
        // 获取源文件夹当前下的文件或目录
        // File[] fileutils = (new File(sourceDir)).listFiles();
        FTPFile[] ftpFiles = ftpClient.listFiles(sourceDir);
        for (int i = 0; i < ftpFiles.length; i++) {
            if (ftpFiles[i].isFile()) {
                copyFile(ftpFiles[i].getName(), sourceDir, targetDir,ftpClient);
            } else if (ftpFiles[i].isDirectory()) {
                copyDirectiory(sourceDir + "/" + ftpFiles[i].getName(), targetDir + "/" + ftpFiles[i].getName(),ftpClient);
            }
        }
    }
    /**
     * 复制文件.
     *
     * @param sourceFileName
     * @param targetDir
     * @throws IOException
     */
    public void copyFile(String sourceFileName, String sourceDir, String targetDir,FTPClient ftpClient) throws IOException {
        InputStream is = null;
        try {
            if (!exists(targetDir)) {
                createDirectory(targetDir,ftpClient);
            }
            // 变更工作路径
            changeWorkingDirectory(sourceDir);
            // 设置以二进制流的方式传输
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            is = ftpClient.retrieveFileStream(sourceFileName);
            // 主动调用一次getReply()把接下来的226消费掉. 这样做是可以解决这个返回null问题
            ftpClient.getReply();

            if (is != null) {
                changeWorkingDirectory(targetDir);
                ftpClient.storeFile(sourceFileName, is);
            }

        } finally {
            // 关闭流
            if (is != null) {
                is.close();
            }
        }
    }
    private boolean changeWorkingDirectory(String path) throws IOException {
        path= Paths.get(path).toString().replace("\\","/");
        if(path.contains(workPath)){
            return this.ftp.changeWorkingDirectory(path);
        }
        this.ftp.changeWorkingDirectory(workPath);
        path=Paths.get(workPath,path).toString().replace("\\","/");
        return this.ftp.changeWorkingDirectory(path);
    }

    public FTPClient getFtp() {
        return ftp;
    }

    public String getHostname() {
        return hostname;
    }

    public void setHostname(String hostname) {
        this.hostname = hostname;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getWorkPath() {
        return workPath;
    }

    public void setWorkPath(String workPath) {
        this.workPath = workPath;
    }
}

猜你喜欢

转载自www.cnblogs.com/songanwei/p/9075147.html
今日推荐