FTP工具类

这是一个Java实现的FTP客户端工具类,提供了连接、上传、下载、创建目录、删除文件等基本操作。类中包含了FTPClient的初始化、设置超时、改变工作目录、创建目录、存储文件、断开连接等方法,支持文件的多线程下载和文件夹的压缩下载。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.log4j.Logger;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.extra.ftp.FtpException;

import java.io.BufferedInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

import javax.servlet.http.HttpServletResponse;

/** 
* @ClassName: FTPTools 
* @Description: TODO
* @author 
* @date 2021-8-5
*  
*/

public class FTPTools {

	/** 地址 */
	public static final String DEFAULT_HOST = "127.0.0.1";
	/** 端口 */
	public static final int DEFAULT_PORT = 21;
	/** 用户 */
	public static final String DEFAULT_USER = "ftp";
	/** 密码 */
	public static final String DEFAULT_PASSWORD = "admin_ftp";

	private static int clientTimeout = 1000 * 30;
	
    //用于打印日志
    private static final Logger log = Logger.getLogger(FTPTools.class);

    /**
     * 	进入文件夹
     * @param ftpClient  
     * @param directory  文件路径
     * @return
     */
    public static boolean cd(FTPClient ftpClient,String directory) {
		if (StrUtil.isBlank(directory)) {
			return false;
		}

		boolean flag = true;
		try {
			flag = ftpClient.changeWorkingDirectory(directory);
		} catch (IOException e) {
			throw new FtpException(e);
		}
		return flag;
	}
    /**
     * 	逻辑判断创建文件夹
     * @param ftpClient
     * @param dir  文件路径
     */
    public static void mkDirs(FTPClient ftpClient,String dir) {
		final String[] dirs = StrUtil.trim(dir).split("[\\\\/]+");

		final String now = pwd(ftpClient);
		if(dirs.length > 0 && StrUtil.isEmpty(dirs[0])) {
			//首位为空,表示以/开头
			cd(ftpClient,StrUtil.SLASH);
		}
		for (int i = 0; i < dirs.length; i++) {
			if (StrUtil.isNotEmpty(dirs[i])) {
				if (false == cd(ftpClient,dirs[i])) {
					//目录不存在时创建
					mkdir(ftpClient,dirs[i]);
					cd(ftpClient,dirs[i]);
				}
			}
		}
		// 切换回工作目录
		cd(ftpClient,now);
	}
    /**
     * 	创建文件夹
     * @param ftpClient
     * @param dir  文件路径
     * @return
     */
	public static boolean mkdir(FTPClient ftpClient,String dir) {
		boolean flag = true;
		try {
			flag = ftpClient.makeDirectory(dir);
		} catch (IOException e) {
			throw new FtpException(e);
		}
		return flag;
	}
	/**
	 * 
	 * @param ftpClient
	 * @return
	 */
	public static String pwd(FTPClient ftpClient) {
		try {
			return ftpClient.printWorkingDirectory();
		} catch (IOException e) {
			throw new FtpException(e);
		}
	}

	/**
	 * 
	 * @param workingPath  服务器的工作目
	 * @param inputStream  要上传文件的输入流
	 * @param saveName    文件保存路径名称
	 * @return
	 */
    public static boolean upload(String workingPath, InputStream inputStream, String saveName) {
        
        return upload(DEFAULT_HOST,DEFAULT_PORT,DEFAULT_USER,DEFAULT_PASSWORD,workingPath, inputStream, saveName);
    }
    /**
     * 	上传
     *
     * @param hostname ip或域名地址
     * @param port  端口
     * @param username 用户名
     * @param password 密码
     * @param workingPath 服务器的工作目
     * @param inputStream 要上传文件的输入流
     * @param saveName    设置上传之后的文件名
     * @return
     */
    public static boolean upload(String hostname, int port, String username, String password, String workingPath, InputStream inputStream, String saveName) {
        boolean flag = false;
        FTPClient ftpClient = new FTPClient();
        ftpClient.setDefaultTimeout(clientTimeout * 1000);
		ftpClient.setBufferSize(1024*1024);
		ftpClient.setDataTimeout(clientTimeout * 1000);
        //1 测试连接
        if (connect(ftpClient, hostname, port, username, password)) {
            String pwd = pwd(ftpClient);

			if (StrUtil.isNotBlank(workingPath)) {
				mkDirs(ftpClient,workingPath);
				boolean isOk = cd(ftpClient,workingPath);
				if (false == isOk) {
					return false;
				}
			}

			// 3 检查是否上传成功
			if (storeFile(ftpClient, saveName, inputStream)) {
			    flag = true;
			    disconnect(ftpClient);
			}
        }
        return flag;
    }
    
    /**
     * 	断开连接
     *
     * @param ftpClient
     * @throws Exception
     */
    public static void disconnect(FTPClient ftpClient) {
        if (ftpClient.isConnected()) {
            try {
                ftpClient.disconnect();
                log.error("已关闭连接");
            } catch (IOException e) {
                log.error("没有关闭连接");
                e.printStackTrace();
            }
        }
    }

    /**
     * 	测试是否能连接
     *
     * @param ftpClient
     * @param hostname  ip或域名地址
     * @param port      端口
     * @param username  用户名
     * @param password  密码
     * @return 返回真则能连接
     */
    public static boolean connect(FTPClient ftpClient, String hostname, int port, String username, String password) {
        boolean flag = false;
        try {
            //ftp初始化的一些参数
            ftpClient.connect(hostname, port);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.setControlEncoding("UTF-8");
            if (ftpClient.login(username, password)) {
                log.info("连接ftp成功");
                flag = true;
            } else {
                log.error("连接ftp失败,可能用户名或密码错误");
                try {
                    disconnect(ftpClient);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } catch (IOException e) {
            log.error("连接失败,可能ip或端口错误");
            e.printStackTrace();
        }
        return flag;
    }

    /**
     * 	上传文件
     *
     * @param ftpClient
     * @param saveName        全路径。如/home/public/a.txt
     * @param fileInputStream 要上传的文件流
     * @return
     */
    public static boolean storeFile(FTPClient ftpClient, String saveName, InputStream fileInputStream) {
        boolean flag = false;
        try {
			ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);		//处理好编码,防止乱码
            if (ftpClient.storeFile(saveName, fileInputStream)) {
                flag = true;
                log.error("上传成功");
                disconnect(ftpClient);
            }
        } catch (IOException e) {
            log.error("上传失败");
            disconnect(ftpClient);
            e.printStackTrace();
        }
        return flag;
    }
    
    /**
     * 	下载文件
     *
     * @param filename  需要下载的文件全路径
     * @return 
     */
    
    public static InputStream downFileByPath(String fileName)
    {
		InputStream in=null;
        FTPClient ftpClient = new FTPClient();
        //1 测试连接
        if (connect(ftpClient, DEFAULT_HOST,DEFAULT_PORT,DEFAULT_USER,DEFAULT_PASSWORD)) {
            try {
    	        in = ftpClient.retrieveFileStream(fileName);
        		
                disconnect(ftpClient);
                
            } catch (IOException e) {
                log.error("工作目录不存在");
                e.printStackTrace();
                disconnect(ftpClient);
            }
        }
        return in;
    }

	/**
	 * 1 多文件下载
	 * @param response HttpServletResponse
	 * @param files[] 待下载文件
	 * @param downloadfile 下载文件文件名+文件类型(a.zip)
	 * @throws Exception
	 * @date 2019年3月29日11:31:35
	 */
	public static void multFileDownload(HttpServletResponse response,List<Map<String,Object>> listF,String downloadfile) throws Exception {

		response.setHeader("Accept-Ranges", "bytes");
		response.setHeader("content-type", "application/octet-stream");
		response.setContentType("multipart/form-data");//1.设置文件ContentType类型,这样设置,会自动判断下载文件类型   
		response.setHeader("Content-Disposition", "attachment;fileName="+downloadfile);
		try {
			ZipOutputStream zipstream=new ZipOutputStream(response.getOutputStream());
            DataInputStream dis=null;
			for (Map<String,Object> file:listF) {
				InputStream instream =(InputStream)file.get("is");
				String fileName =file.get("file").toString();
				if (instream==null) {
					continue;
				}
                dis=new DataInputStream(new BufferedInputStream(instream));
				ZipEntry entry = new ZipEntry(fileName);
				zipstream.putNextEntry(entry);
				
				byte[] b = new byte[1024];
				int length;
				while((length=instream.read(b))>0){
					zipstream.write(b,0,length);  
				}
				
				instream.close();
				if(dis!=null){
                    dis.close();
                }
				zipstream.closeEntry();
				zipstream.flush();
			}
			zipstream.finish();
			zipstream.close();
		} catch (IOException e) {   
			new RuntimeException(e.getMessage());   
		}  
	}
    
    /**
     * 下载文件并且重命名
     *
     * @param fullFile  文件全路径
     * @param changename  修改的文件名
     */
    public static boolean downFile(String fullFile,String changename)
    {
    	return downFile(DEFAULT_HOST,DEFAULT_PORT,DEFAULT_USER,DEFAULT_PASSWORD,fullFile,changename);
    }
    
    /**
     * 	下载文件
     *
     * @param hostname  ip或域名地址
     * @param port      端口
     * @param username  用户名
     * @param password  密码
     * @param fullFile  文件全路径
     * @param changename  修改的文件名
     * @return 
     */
    public static boolean downFile(String hostname, int port, String username, String password, String fullFile,String changename)
    {
    	boolean flag = false;
        FTPClient ftpClient = new FTPClient();
        //1 测试连接
        if (connect(ftpClient, hostname, port, username, password)) {
            try {
                
                flag = true;
                
                File file=new File(fullFile);
                OutputStream os = new FileOutputStream(file);
                //ftpClient.setControlEncoding("GBK");
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);	//处理好编码,防止乱码
                //如果文件名中含有中文,retrieveFile文件时会找不到FTP上的文件,导致保存在本地的是一个空文件,所以也要转换一下
                ftpClient.retrieveFile(changename, os);
                os.close();
        		
                disconnect(ftpClient);
                
            } catch (IOException e) {
                log.error("工作目录不存在");
                e.printStackTrace();
                disconnect(ftpClient);
            }
        }
        return flag;
    }
    
    /**
     * 	下载文件
     *
     * @param fullFile  文件全路径
     * @param changename  修改的文件名
     * @param os   文件输出流
     * @return 
     */
    public static boolean downFile(String fullFile,String changename,OutputStream os)
    {
    	return downFile(DEFAULT_HOST,DEFAULT_PORT,DEFAULT_USER,DEFAULT_PASSWORD,fullFile,changename,os);
    }
    
    /**
     * 	下载文件
     *
     * @param hostname  ip或域名地址
     * @param port      端口
     * @param username  用户名
     * @param password  密码
     * @param fullFile  文件全路径
     * @param changename  修改的文件名
     * @param os   文件输出流
     * @return 
     */
    public static boolean downFile(String hostname, int port, String username, String password, String fullFile,String changename,OutputStream os)
    {
    	boolean flag = false;
        FTPClient ftpClient = new FTPClient();
        //1 测试连接
        if (connect(ftpClient, hostname, port, username, password)) {
            try {
            
                flag = true;
                //ftpClient.setControlEncoding("GBK");
                ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);	//处理好编码,防止乱码
                //如果文件名中含有中文,retrieveFile文件时会找不到FTP上的文件,导致保存在本地的是一个空文件,所以也要转换一下
                ftpClient.retrieveFile(changename, os);
                os.close();
        		
                disconnect(ftpClient);
                
            } catch (IOException e) {
                log.error("工作目录不存在");
                e.printStackTrace();
                disconnect(ftpClient);
            }
        }
        return flag;
    }
    
    /**
     * 	是否存在文件
     * @param fullFile
     * @return
     */
    public static boolean existFile(String fullFile)
    {
    	return existFile(DEFAULT_HOST,DEFAULT_PORT,DEFAULT_USER,DEFAULT_PASSWORD,fullFile);
    }
    /**
     * 	查看文件是否存在
     *
     * @param hostname  ip或域名地址
     * @param port      端口
     * @param username  用户名
     * @param password  密码
     * @param fullFile  文件全路径
     * @return 
     */
    public static boolean existFile(String hostname, int port, String username, String password, String fullFile)
    {
    	boolean flag = false;
        FTPClient ftpClient = new FTPClient();
        //1 测试连接
        if (connect(ftpClient, hostname, port, username, password)) {
            try {
                //2 检查工作目录是否存在
            	FTPFile[] files = ftpClient.listFiles(fullFile);
    			if(files!=null&&files.length>0){
                    flag = true;
                    disconnect(ftpClient);
                }
            } catch (IOException e) {
                log.error("工作目录不存在");
                e.printStackTrace();
                disconnect(ftpClient);
            }
        }
        return flag;
    }
    /**
     * 	删除文件
     * @param fullFile
     * @return
     */
    public static boolean deleteFile(String fullFile) {
        return deleteFile(DEFAULT_HOST,DEFAULT_PORT,DEFAULT_USER,DEFAULT_PASSWORD,fullFile);
    }
    /**
     * 	删除文件
     *
     * @param hostname  ip或域名地址
     * @param port      端口
     * @param username  用户名
     * @param password  密码
     * @param fullFile  文件全路径
     * @return 
     */
    public static boolean deleteFile(String hostname, int port, String username, String password, String fullFile)
    {
    	boolean flag = false;
        FTPClient ftpClient = new FTPClient();
        //1 测试连接
        if (connect(ftpClient, hostname, port, username, password)) {
            try {
            	
            	if(ftpClient.deleteFile(fullFile)){
                    flag = true;
                    disconnect(ftpClient);
                }
                
            } catch (IOException e) {
                log.error("工作目录不存在");
                e.printStackTrace();
                disconnect(ftpClient);
            }
        }
        return flag;
    }
    
    
    public static void main(String[] args) {
    	//Login failed for user [anonymous], reply code is: [530]
    	InputStream is=FileUtil.getInputStream("F:/学习开发经验连接.txt");
    	upload("/demo",is ,"111.txt");
	}
}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值