使用FTPClient实现文件的上传下载

操作系统环境:windows7

本地IP地址:192.168.0.110

FTP保存目录:D:/bfp/FTP

1、FTP的搭建:可以使用win7自带的FTP,搭建方法可以百度。我使用的是"ftpserversetup_10232(FTP搭建工具).exe",安装过程很简单,根据提示下一步下一步操作即可。

2、启动服务器

3、访问FTP:随便打开一个目录,在地址栏上输入:ftp://192.168.0.110/,回车,第一次登陆需要输入搭建FTP时创建的用户名和密码,登陆成功后就会看到FTP中的文件(注意权限,必须有相应权限

4、文件的上传下载:图形化界面的上传下载比较简单,这里贴一下使用Java代码实现的上传下载。

说明:文件夹为中文的情况没有处理,可能会出现中文乱码

代码如下:

4.1 FTP用户名、密码等,及main测试方法

private static String ftpIP="192.168.0.110";//FTP地址
private static int port = 21;//端口号
private static String username="wjl";//登陆ftp的用户名
private static String pwd="123456";//登陆ftp的密码
private static FTPClient ftpClient=null;//FTP客户端代理
private static int timeout=2*60*100;//2分钟,以毫秒为单位
/**
 * 该方法用来测试FTP的上传和下载
 * @throws UnsupportedEncodingException 
 */
public static void main(String[] args){
	boolean result=false;
	/*
	//1、连接FTP
	result = connectFTPServer();
	if(result){
		System.out.println("连接成功");
	}else{
		System.out.println("连接失败");
	}
	*/
	/*
	//2、上传单个文件
	result = uploadFile(new File("D:\\temp\\1.jpg"));
	if(result){//下载完成
		System.out.println("上传完成!");
		closeConnect();//关闭连接
	}
	*/
	
	/*
	//3、上传整个文件夹
	result = uploadFile(new File("D:\\temp"));
	if(result){//下载完成
		System.out.println("上传完成!");
		closeConnect();//关闭连接
	}
	*/
	/*
	//4、下载单个文件
	//result = downloadFile(new File("\\photo\\1.jpg"),new File("D:\\temp2\\123.jpg"));//指定文件名
	result = downloadFile(new File("\\photo\\1.jpg"),new File("D:\\temp2"));//只指定目录
	if(result){//下载完成
		System.out.println("下载完成!");
		closeConnect();//关闭连接
	}
	*/
	//5、下载文件夹
	result = downloadFile(new File("\\photo"),new File("D:\\temp22"));
	//result = downloadFile(new File("\\photo\\1.jpg"),new File("D:\\temp2"));//只指定目录
	if(result){//下载完成
		System.out.println("下载完成!");
		closeConnect();//关闭连接
	}
}

4.2连接FTP

/**
 * 该方法用来连接FTP
 * @return true:连接成功 false:链接失败
 * **/
private static boolean connectFTPServer(){  
    boolean result = true;  
    if(ftpClient==null){//说明还没有初始化
        int reply;
        try {  
        	ftpClient = new FTPClient();
        	//注:必须先login然后再设置其他属性,否则即便文件上传成功文件也会损坏
        	//ftpClient.connect(ftpIP, port);//连接
        	ftpClient.connect(ftpIP);//连接FTP客户端
        	ftpClient.setDefaultPort(port);//端口号
        	ftpClient.login(username, pwd);//登陆   
        	
        	ftpClient.setControlEncoding("UTF-8");//编码
        	ftpClient.setDataTimeout(timeout);//设置超时时间
        	ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);//设置文件类型(二进制)
        	ftpClient.setBufferSize(1024);//缓冲区大小
        	
	        reply = ftpClient.getReplyCode();  
	        if (!FTPReply.isPositiveCompletion(reply)) {//连接失败 
	        	ftpClient.disconnect();//关闭连接  
	            result=false;  
	        }  
        }catch (SocketException e) {
        	result = false;
            e.printStackTrace();
            System.err.println("登录ftp服务器 " + ftpIP + " 失败,连接超时!");
        } catch (IOException e) {
        	result = false;
            e.printStackTrace();
            System.err.println("登录ftp服务器 " + ftpIP + " 失败,FTP服务器无法打开!");
        } 
    }
    return result;  
} 

4.3、上传文件(包括上传文件和文件夹)

/**  
 * 上传文件
 * 单个文件上传至:FTP根目录+当前年月日+随机名称.上传文件后缀名
 * 多个文件上传至:FTP根目录+当前年月日+上传的文件夹
 * @param file:要上传的文件或文件夹
 * @return true:上传成功 false:上传失败 
 */   
public static boolean uploadFile(File file) {   
    boolean result = true;
	FileInputStream fis = null;   
    try {   
    	connectFTPServer();//连接FTP
    	
    	//根据当前时间对文件进行分类
    	String filePath = getFilePath();
    	ftpClient.makeDirectory(filePath);//在ftp下创建目录
    	ftpClient.changeWorkingDirectory(filePath);//切换目录
    	
    	if(isDir(file.getPath())){//上传的是文件夹
        	String changeWorkDirectory = filePath+file.getPath().substring(2);//截取掉最开始的D:两个字段
        	//System.out.println("切换目录:"+changeWorkDirectory);
    		ftpClient.makeDirectory(changeWorkDirectory);//使用文件夹原本的名称并创建
        	ftpClient.changeWorkingDirectory(changeWorkDirectory);//切换目录
        	
            String[] files = file.list();//循环文件夹下的所有文件
            for (int i = 0; i < files.length; i++) {  
                File file1 = new File(file.getPath() + File.separator + files[i]);  
                if (file1.isDirectory()) {//若还有文件夹,那么递归上传  
                	uploadFile(file1);  
                	ftpClient.changeToParentDirectory();//切换至父级目录  
                } else { //若是文件了,那么直接上传
                    File file2 = new File(file.getPath() + File.separator + files[i]);  
                    fis = new FileInputStream(file2);  
                    ftpClient.storeFile(file2.getName(), fis);//使用原本的名称
                    System.out.println("文件"+file2.getPath()+"上传成功,上传目录:"+(changeWorkDirectory+File.separator+file2.getName()));
                }  
            }  
        }else{
        	//单个文件
        	File srcFile = new File(file.getPath()); //选择要上传的文件
            fis = new FileInputStream(srcFile);  
           
            //为了避免文件名重复被覆盖,此处选择随机命名
            String fileName = System.currentTimeMillis()+getFileSuffix(file.getName());//获取文件路径和名称
        	ftpClient.storeFile(fileName, fis); //保存的ftp服务器上的文件名,上传ftp  
        	System.out.println("文件"+file.getPath()+"上传成功,上传目录:"+(filePath+fileName));
        }
    } catch (Throwable e) {  
    	result=false;
        e.printStackTrace();   
        throw new RuntimeException("文件上传失败!", e);   
    } finally {   
    	//此处不能关闭ftpClient,因为当上传文件夹时会递归调用,待递归调用结束时会调用该方法,而主方法尚未完成,因此会导致空指针异常
    	IOUtils.closeQuietly(fis); //关闭fis  
    } 
    return result;
}

4.4 下载文件(包括下载文件和文件夹)

/**  
 * 下载文件
 * @param ftpFile:要下载的文件或文件夹
 * @param dstFile:保存的文件或文件夹,若指定文件名称就使用指定的名称和目录,若是文件夹则文件名称采用ftp上要下载的文件的名称
 */   
    public static boolean downloadFile(File ftpFile,File dstFile) {
    	boolean result = true;
        FileOutputStream fos = null;   
  
        try {   
        	connectFTPServer();//连接FTP
    	
        //判断要下载的是个文件夹还是个文件
        if(isDir(ftpFile.getPath())){
        	ftpClient.changeWorkingDirectory(ftpFile.getPath());//切换目录
            String[] files = ftpClient.listNames();//循环文件夹下的所有文件
            String path = "";
            for (int i = 0; i < files.length; i++) {
            	path = ftpFile.getPath() + File.separator + files[i];
            	File file1 = new File(path);//FTP上的文件名称
                if (isDir(file1.getPath())) {//若还有文件夹,那么递归上传  
                	downloadFile(file1,dstFile);  
                } else { //若是文件了,那么直接下载
                	//判断保存到本地的目录
                	String localParent = "";
                	if(isDir(dstFile.getPath())){//告知了一个文件夹
                		if(!dstFile.exists()){dstFile.mkdirs();}
                		localParent = dstFile.getPath();
                	}else{
                		if(!dstFile.getParentFile().exists()){dstFile.getParentFile().mkdirs();}
                		localParent=dstFile.getParentFile().getPath();
                	}
                	//本地路径+FTP上选定文件夹的目录+文件名称
                	String localFileName = localParent+File.separator+ftpFile.getPath() + File.separator + files[i];
                	File localFile = new File(localFileName);
                	if(!localFile.getParentFile().exists()){localFile.getParentFile().mkdirs();}
                	fos = new FileOutputStream(localFile); //下载到本地的文件的名字  
                    ftpClient.retrieveFile(file1.getName(), fos); //从ftp上下载到本地  
                    System.out.println(file1.getPath()+"下载至:"+localFileName+",下载成功");
                }  
            }
        }else{//单个文件
        	//从ftp上下载文件的目录
        	ftpClient.changeWorkingDirectory(ftpFile.getParent());//切换至选定文件夹的上一级目录
        	
        	//保存的目录
        	String newFileName = "";
        	
        	//判断是否存在
        	if(isDir(dstFile.getPath())){//将文件保存到一个目录下
        		if(!dstFile.exists()){dstFile.mkdirs();}
        		//文件名称格式:指定目录+FTP中文件的名称
        		newFileName = dstFile.getPath()+File.separator+ftpFile.getName();
        	}else{//将文件保存为指定的文件
        		if(!dstFile.getParentFile().exists()){dstFile.getParentFile().mkdirs();}
        		newFileName=dstFile.getPath();
        	}
            System.out.println("文件保存到的目录:"+newFileName);
            fos = new FileOutputStream(newFileName); //下载到本地的文件的名字  
            
            ftpClient.retrieveFile(ftpFile.getName(), fos); //从ftp上下载到本地
            System.out.println(ftpFile.getPath()+"下载成功,下载至:"+newFileName);
        }
        
    } catch (IOException e) { 
    	result = false;
        e.printStackTrace();   
        throw new RuntimeException("下载文件失败!", e);   
    } finally { 
    	//此处不能关闭ftpClient,因为当上传文件夹时会递归调用,待递归调用结束时会调用该方法,而主方法尚未完成,因此会导致空指针异常
        IOUtils.closeQuietly(fos);   
    } 
    return result;
}

4.5 关闭连接

/**
 * 关闭连接
 */
public static void closeConnect() {
	try {
		if (ftpClient != null) {
			ftpClient.disconnect();
		}
	} catch (Exception e) {
		e.printStackTrace();
		throw new RuntimeException("关闭FTP连接发生异常!", e);
	}
}

4.6、其他的一些辅助方法

/**
 * 该方法用来判断给定的字符串是不是文件夹
 * @param filePath:可能是文件夹,也可能是文件
 * @return boolean :true:文件夹 false:文件
 * **/
public static boolean isDir(String filePath){
	boolean result = false;
	//获取最后一个/的后面部分
	filePath = filePath.substring(filePath.lastIndexOf("/") + 1); // 在这里可以记录用户和文件信息
	
	//判断是否有.若没有,说明是文件夹,否则是文件(也可能是带有.的文件夹,此处不处理)
	if(filePath.indexOf(".")!=-1){//说明
		result = false;
	}else{//没有,是文件夹
		result=true;
	}
	return result;
}

//该方法用来获取文件的后缀名
public static String getFileSuffix(String fileName){
	fileName = fileName.substring(fileName.lastIndexOf("\\") + 1); // 在这里可以记录用户和文件信息
	fileName = fileName.substring(fileName.lastIndexOf("."));
	return fileName;
}

/**
 * 该方法用来获取文件的保存名称,包括路径和名称
 * @param fileName:不包含目录的文件名称
 * @return yyyyMMdd/System.currentTimeMillis().后缀名
 * **/
public static String getFileName(String fileName){
	GregorianCalendar ggcalendar=new GregorianCalendar(Locale.CHINA);
	int year = ggcalendar.get(Calendar.YEAR);;
	int month = ggcalendar.get(Calendar.MONTH)+1;
	int date = ggcalendar.get(Calendar.DATE);
	return  (year+""+month+""+date)+File.separator+System.currentTimeMillis()+getFileSuffix(fileName);
}

/**
 * 该方法用来获取文件的保存路径
 * @param fileName:不包含目录的文件名称
 * @return yyyyMMdd/System.currentTimeMillis().后缀名
 * **/
public static String getFilePath(){
	GregorianCalendar ggcalendar=new GregorianCalendar(Locale.CHINA);
	int year = ggcalendar.get(Calendar.YEAR);;
	int month = ggcalendar.get(Calendar.MONTH)+1;
	int date = ggcalendar.get(Calendar.DATE);
	return File.separator+(year+""+month+""+date)+File.separator;
}

/**
 * 删除一个文件
 */
public static boolean deleteFile(String filename) {
    boolean result = true;
    try {
    	connectFTPServer();
    	File f = new File(filename);
    	System.out.println(f.exists());
    	result = ftpClient.deleteFile(filename);
    } catch (IOException e) {
    	result=false;
    	e.printStackTrace();
    	throw new RuntimeException("删除文件"+filename+"失败!", e); 
    }
    return result;
}

/**
 * 删除指定目录:先删除该目录下的文件,最后删除目录
 */
public static void deleteDirectory(String pathname) {
	try {
    	connectFTPServer();
        File file = new File(pathname);
        if (file.isDirectory()) {
            File file2[] = file.listFiles();
            for(int i=0;i<file2.length;i++){
            	deleteDirectory(file.getPath() + File.separator + file2[i]);
            }
        } else {//删除文件
            deleteFile(pathname);
        }
        ftpClient.removeDirectory(pathname);
    }catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException("删除目录失败!", e); 
    }
}

/**
 * 删除空目录
 */
public static void deleteEmptyDirectory(String pathname) {
    try {
    	connectFTPServer();
        ftpClient.removeDirectory(pathname);
    } catch (IOException e) {
        e.printStackTrace();
        throw new RuntimeException("删除空目录失败!", e); 
    }
}

/**
 * 列出服务器上文件和目录
 */
public static void listRemoteFiles(String regStr) {
	connectFTPServer();
    try {
            String files[] = ftpClient.listNames(regStr);
            if (files == null || files.length == 0)
                    System.out.println("没有任何文件!");
            else {
                    for (int i = 0; i < files.length; i++) {
                            System.out.println(files[i]);
                    }
            }
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("列出FTP服务器上指定目录的文件时失败失败!", e); 
    }
}

/**
 * 列出Ftp服务器上的所有文件和目录
 */
public static void listRemoteAllFiles() {
	connectFTPServer();
    try {
        String[] names = ftpClient.listNames();
        for (int i = 0; i < names.length; i++) {
            System.out.println(names[i]);
        }
    } catch (Exception e) {
        e.printStackTrace();
        throw new RuntimeException("列出FTP服务器上所有文件和目录时失败!", e); 
    }
}

/**
 * 在服务器上创建一个文件夹
 */
public static boolean makeDirectory(String dir) {
	connectFTPServer();
    boolean result = true;
    try {
    	result = ftpClient.makeDirectory(dir);
    } catch (Exception e) {
    	result = false;   
    	e.printStackTrace();
        throw new RuntimeException("创建文件夹失败!", e); 
    }
    return result;
}

参考链接:

1、http://747017186.iteye.com/blog/2211514
2、http://lavasoft.blog.51cto.com/62575/100386/

推荐链接:

1、官网FTPClient的API:http://commons.apache.org/proper/commons-net/apidocs/org/apache/commons/net/ftp/FTPClientConfig.html
2、FTPClient各个属性说明:http://blog.csdn.net/hazard88/article/details/8676119

猜你喜欢

转载自1017401036.iteye.com/blog/2266160
今日推荐