Java操作FTP

使用IIS方式搭建FTP

Windows下使用FileZilla搭建FTP

1、与FTP服务器建立连接

/**
 * 初始化客户端并完成对服务端的连接
 * @param server 服务端地址
 * @param port 端口号
 * @param username 用户名
 * @param password 密码
 * @param path 远程路径 值可以为空
 * @throws SocketException
 * @throws IOException
 */
public static FTPClient connectServer(String server, int port, String username,String password, String path)  {
	if(null == path){
		path = "";
	}
	try {
		FTPClient ftp = new FTPClient();
		//下面四行代码必须要,而且不能改变编码格式,否则不能正确下载中文文件
		// 如果使用serv-u发布ftp站点,则需要勾掉“高级选项”中的“对所有已收发的路径和文件名使用UTF-8编码”
		ftp.setControlEncoding("GBK");
		FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);
		conf.setServerLanguageCode("zh");
		ftp.configure(conf);
		
		ftp.connect(server, port);
		ftp.setDataTimeout(120000);

		// 判断ftp是否存在
		if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {	
			ftp.disconnect();	// 如果不存在,断开ftp连接
			log.warn(server + "  FTP拒绝连接");
		}
		// 登陆ftp
		boolean flag = ftp.login(username, password);
		if (flag) {
			log.info("FTP登录成功。");
		}else {
			log.error("FTP登录失败。");
		}
		
		// 根据输入的路径,切换工作目录。这样ftp端的路径就可以使用相对路径了
		if (path.length() != 0) {
			if (path != null && !"".equals(path.trim())) {
				// 对路径按照‘/’进行切割,一层一层的进入
				String[] pathes = path.split("/");
				for (String onepath : pathes) {
					if (onepath == null || "".equals(onepath.trim())) {
						continue;
					}               
					if (!ftp.changeWorkingDirectory(onepath)) {
						ftp.makeDirectory(onepath);
						boolean flagDir = ftp.changeWorkingDirectory(onepath);
						log.info(ftp.printWorkingDirectory());
						if (flagDir) {
							log.info("成功连接ftp目录:" + ftp.printWorkingDirectory());
						} else {
							log.error("未能连接ftp目录:" + ftp.printWorkingDirectory());
						}
					}
				}
			}
		}
		return ftp;
	}catch(SocketException e){
		e.printStackTrace();
		return null;
	}
	catch (IOException e) {
		e.printStackTrace();
		return null;
	}
}

2、返回目录下的所有文件(包括文件夹)

/**
 * 返回给定目录下的所有文件(包括文件夹)
 * @param path
 * @return FTPFile组成的集合
 * @throws IOException
 */
public static List<String> getFileList(FTPClient ftp,String path) throws IOException {
	
	ftp.changeWorkingDirectory(path);//切换对应路径下
	log.info("FTP当前目录:"+ftp.printWorkingDirectory());
	FTPFile[] ftpFiles = ftp.listFiles();    // ftpFiles.length返回当前目录下的文件数
	List retList = new ArrayList();
	if (ftpFiles == null || ftpFiles.length == 0) {
		return retList;
	}
	for (int i = 0; i < ftpFiles.length; i++) {
		FTPFile ftpFile = ftpFiles[i];
//		if (ftpFile.isFile()) {	// 判断是否为文件,这样返回的就是所有的文件名
//			retList.add(ftpFile.getName());
//		}
		retList.add(ftpFile.getName());
	}
	return retList;
}

3、获取指定路径下的所有文件(不管多少文件夹下)

/**
 * 递归遍历文件夹以及子文件夹的文件
 * 获取指定路径下的所有文件(不管多少文件夹下)
 * @param pathName 
 * @param filePathList
 * @throws IOException
 */
public static void getFileListRecursion(FTPClient ftp,String pathName, List<String> filePathList) throws IOException {
	
	if(null == pathName){
		pathName = "/";
	}else{
		pathName = pathName.replace("\", "/");
	}
	if(!pathName.startsWith("/")){
		pathName ="/"+pathName;
	}
	if(!pathName.endsWith("/")){
		pathName = pathName + "/";
	}
	
	ftp.changeWorkingDirectory(pathName);
	FTPFile[] files = ftp.listFiles();
	for (int i = 0; i < files.length; i++) {
		if (files[i].isFile()) {
			log.info("得到文件:" + files[i].getName());
			log.info("--------------");
			filePathList.add(ftp.printWorkingDirectory()+"/"+files[i].getName());
		} else if (files[i].isDirectory()) {
			getFileListRecursion(ftp,pathName + files[i].getName() + "/", filePathList);
		}
	}
}

4、删除指定目录(递归)

/**
 * 删除指定目录下的所有文件
 * @param ftp
 * @param pathname
 * @return
 */
public static boolean removeAll(FTPClient ftp, String pathname) {
	try {
		ftp.removeDirectory(pathname);
		FTPFile[] files = ftp.listFiles(pathname);
		for (FTPFile f : files) {
			if (f.isDirectory()) {
				removeAll(ftp,pathname + "/" + f.getName());
				boolean isDelDir = ftp.removeDirectory(pathname);
				log.info("FTP目录是否已删除>>"+isDelDir);
			}
			if (f.isFile()) {
				boolean isDelFile = ftp.deleteFile(pathname + "/" + f.getName());
				ftp.removeDirectory(pathname);
				log.info("FTP文件是否已删除>>"+isDelFile);
			}
		}
	} catch (IOException e) {
		e.printStackTrace();
		return false;
	}
	return true;
}

5、上传文件,并重命名

/**
 * 上传文件,并重命名.
 * @param filePathName 上传的文件,包含目录的文件名
 * @param newName 新的文件名
 * @return 上传结果,是否成功.
 * @throws IOException
 */
public static boolean uploadFile(FTPClient ftp,String filePathName, String newName)
		throws IOException {
	boolean flag = false;
	InputStream iStream = null;
	try {
		log.info("ftp new file name : "+newName);
		ftp.setControlEncoding("GBK");
		iStream = new FileInputStream(filePathName);
		ftp.setFileType(FTPClient.BINARY_FILE_TYPE);  
		//将当前数据连接模式设置为PASSIVE_LOCAL_DATA_CONNECTION_MODE,即:被动模式
		ftp.enterLocalPassiveMode();
		//将流写到服务器
		ftp.storeFile(new String(filePathName.getBytes("GBK"),"iso-8859-1"),iStream);
		flag = ftp.storeFile(newName, iStream);
	} catch (IOException e) {
		flag = false;
		return flag;
	} finally {
		if (iStream != null) {
			iStream.close();
		}
	}
	return flag;
}

6、从ftp上下载文件到本地

/**
 * 从ftp上下载文件到本地
 * @param ftpClient:ftp连接
 * @param remoteFilepath:ftp服务器端路径
 * @param localFilePath:本地路径
 * @return 是否下载成功
 */
public static boolean downloadFileFromFtp(FTPClient ftpClient,String remoteFilepath,String localFilePath){
	
	boolean flag = false;
	try {
		//判断本地文件是否已经存在,如果已经存在,则无需下载
		//FTPClient ftpClient = FtpUtil.connectServer(ftp);
		File localFile = new File(localFilePath);
		if (!localFile.exists()) {
			InputStream inputStream = FtpUtil.downFile(ftpClient,remoteFilepath);
			if (inputStream != null) flag = SystemUtil.inputStreamToFile(inputStream, localFilePath);
		}else {
			if (localFile.length() == 0) {
				log.info("文件大小为0,即将为您重新下载!");
				localFile.delete();
				InputStream inputStream = FtpUtil.downFile(ftpClient,remoteFilepath);
				if (inputStream != null) flag = SystemUtil.inputStreamToFile(inputStream, localFilePath);	// 将文件流转化为本地文件
			}else{
				log.info("本地文件已存在.......");
				flag = true;
			}
		}
		FtpUtil.closeServer(ftpClient);
		return flag;
	} catch (Exception e) {
		flag = false;
		log.error("从FTP下载文件到本地失败...");
		log.error(e);
		e.printStackTrace();
		return flag;
	}
}
	
/**
 * 将文件流转化为本地文件
 * @param inputStream
 * @param localFilePath
 * @return boolean
 * @throws IOException 
 */
public static boolean inputStreamToFile(InputStream inputStream,String localFilePath) throws IOException {
	File newDir = new File(localFilePath.replace("\", "/").substring(0, localFilePath.lastIndexOf("\")));
	if (!newDir.exists()) newDir.mkdirs();
	FileOutputStream fs= new FileOutputStream(localFilePath);
	try {
		/*FileChannel fc= ((FileInputStream) inputStream).getChannel();  
		log.info("文件大小:"+fc.size());*/
		int bytesum = 0;
		int byteread = 0;
		
		byte[] buffer = new byte[1024];
		long startTime = System.currentTimeMillis();
		while ((byteread = inputStream.read(buffer)) != -1) {
			bytesum += byteread; // 字节数 文件大小
			fs.write(buffer, 0, byteread);
		}
		fs.flush();
		long endTime = System.currentTimeMillis();
		log.info("将文件流转化为本地文件耗时/毫秒:"+(endTime-startTime));
		return true;
	} catch (Exception e) {
		log.error("将文件流转化为本地文件失败",e);
		return false;
	}finally{
		fs.close();
	}
}

7、获取下一级目录列表 文件+文件夹(返回list<PathVo>)

/**
 * 获取下一级目录列表 文件+文件夹(返回list<PathVo>)
 * @param ftp
 * @param pathName
 * @return
 * @throws IOException
 */
public static List<PathVo> getNextDirectory(FTPClient ftp,String pathName) throws IOException {
	log.info("Ftp中pathName:"+pathName);
	List<PathVo> filePathList = new ArrayList<PathVo>();
	if(null == pathName) pathName = "/";
	else pathName = pathName.replace("\", "/");
	if(!pathName.startsWith("/")) pathName ="/"+pathName;
	if(!pathName.endsWith("/")) pathName = pathName + "/";
	
	boolean flag = ftp.changeWorkingDirectory(pathName);
	if (!flag) {
		log.info("重定位失败。");
		return filePathList;
	}
	log.info("目录切换"+ftp.printWorkingDirectory());
	//ftp.enterLocalActiveMode();//主动模式,默认
	ftp.enterLocalPassiveMode();//被动模式
	//ftp.configure(new FTPClientConfig("dist.dgp.util.fileZillaPlugin.UnixFTPEntryParser"));//FileZilla安装FTP时使用
	String[] list = ftp.listNames();
	System.out.println(list.length);
	FTPFile[] files = ftp.listFiles();
	if (files == null || files.length == 0) {
		ftp.changeToParentDirectory();
		return filePathList;
	}
	log.info("文件长度:"+files.length);
	for (int i = 0; i < files.length; i++) {
		PathVo vo = new PathVo();
		if (files[i].isFile()) {
			vo.setType("file");
			vo.setFullPath(pathName+files[i].getName());
			vo.setSize(formatSize(files[i].getSize()));
			vo.setLastModified(getFileLastModified(files[i].getTimestamp().getTimeInMillis()));
			vo.setLabel(files[i].getName());
			vo.setExtension(files[i].getName().substring(files[i].getName().lastIndexOf(".")+1));
			vo.setChildren(null);
			filePathList.add(vo);
			
		} else if (files[i].isDirectory()) {
			vo.setType("folder");
			vo.setFullPath(pathName+files[i].getName());
			vo.setLabel(files[i].getName());
			vo.setLastModified(getFileLastModified(files[i].getTimestamp().getTimeInMillis()));
			vo.setChildren(getNextDirectory(ftp,pathName + files[i].getName() + "/"));
			filePathList.add(vo);
		}
	}
	log.info("filePathList.size():"+filePathList.size());
	return filePathList;
}

8、获取文件最后编辑时间

/**
 * 获取文件最后编辑时间
 * @param filename
 * @return
 */
public static String getFileLastModified(long timeInMillis) {
	SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm");
	Calendar cal = Calendar.getInstance();
	cal.setTimeInMillis(timeInMillis);
	return sdf.format(cal.getTime());
}

9、其他

FTPClient ftp = new FTPClient();

ftp.logout();	// 关闭ftp连接

ftp.setFileType(fileType);	// 设置ftp的文件传输类型

ftp.changeWorkingDirectory(path);	// 改变ftp的工作目录

ftp.removeDirectory(path);	// 删除一个FTP服务器上的目录(如果为空)

ftp.deleteFile(pathName);	// 删除文件
原文地址:https://www.cnblogs.com/x54256/p/9354872.html