操作系统环境: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