java操作FTP还是很方便的,有多种开源支持,这里在apache开源的基础上自己进行了一些设计,使用起来更顺手和快捷。
思路:
1.设计FTPHandler接口,可以对ftp,sftp进行统一操作,比如上传,下载,删除,获取关闭连接等
2.对FTP和SFTP的实现
3.设计一个工厂(考虑以后可能有sftp,ftp两种,目前只实现一种FTP的),用来生成FTPHandler
4.简单使用说明
作为码农,上代码更实在。
接口 FTPHandler.java
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketException; import org.apache.commons.net.ftp.FTPClient; public interface FTPHandler { /** * 获取连接 * @return * @throws SocketException * @throws IOException */ public boolean connect() throws SocketException, IOException; /** * 上传文件 * @param remotePath 要保存到的远程ftp目录 * @param originalFilename 要保存为远程ftp文件名 * @param is 输入流 * @return */ public boolean uploadFile(String remotePath,String originalFilename, InputStream is); /** * 下载文件 * @param remotePath 文件所在的远程ftp目录 * @param filename 文件名 * @param os 输出流 * @return * @throws IOException */ public boolean downFile(String remotePath,String filename, OutputStream os) throws IOException; /** * 删除文件 * @param remotePath 文件所在ftp目录 * @param filename 文件名 * @return * @throws IOException */ boolean deleteFiles(String remotePath,String filename) throws IOException; /** * 关闭客户端 * @param ftpClient */ public void closeClient(FTPClient ftpClient); }
实现类 FTPHandlerImpl.java
import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.SocketException; import java.util.Properties; import org.apache.commons.lang.StringUtils; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class FTPHandlerImpl implements FTPHandler { private static final Logger LOGGER= LoggerFactory.getLogger(FTPHandlerImpl.class); private static String url=""; private static int port=21; private static String username=null; private static String password=null; private static String remotePath=null; private FTPClient ftpClient = null; static { Properties configP; try { configP = PropertiesUtils.getWebLoProperties("configure"); url = configP.getProperty("downFileService.ftp.url"); username = configP.getProperty("downFileService.ftp.username"); password = configP.getProperty("downFileService.ftp.password"); remotePath = configP.getProperty("downFileService.ftp.remotePath"); // localPath = configP.getProperty("downFileService.ftp.localPath"); } catch (Exception e) { e.printStackTrace(); } } public FTPHandlerImpl() { FTPClient ftpClient = new FTPClient(); this.ftpClient=ftpClient; } @Override public boolean connect() throws SocketException, IOException { boolean success=true; ftpClient.connect(url, port); boolean login = ftpClient.login(username, password); int replyCode = ftpClient.getReplyCode(); if (!FTPReply.isPositiveCompletion(replyCode)) { success=false; } return success&&login; } @Override public boolean uploadFile(String _remotePath,String storeFilename, InputStream is) { boolean success=false; try { // 切换到path指定的目录 if(StringUtils.isBlank(_remotePath)){ _remotePath=remotePath; } createOrChangeDir(_remotePath); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.setFileTransferMode(FTP.BINARY_FILE_TYPE); success = ftpClient.storeFile(storeFilename, is); is.close(); } catch (IOException e) { e.printStackTrace(); } closeClient(ftpClient); return success; } @Override public boolean downFile(String _remotePath,String filename, OutputStream os) throws IOException { // 解决图片上传失真 //解决图片下载失真 // 切换到path指定的目录 if(StringUtils.isBlank(_remotePath)){ _remotePath=remotePath; } createOrChangeDir(_remotePath); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.setFileTransferMode(FTP.BINARY_FILE_TYPE); FTPFile[] ftpFiles = ftpClient.listFiles(); boolean success=false; for (FTPFile file : ftpFiles) { if (file.getName().equals(filename)) { filename = file.getName(); success = ftpClient.retrieveFile(filename, os); break; } } closeClient(ftpClient); return success; } @Override public boolean deleteFiles(String _remotePath,String fileName) throws IOException { // 切换到path指定的目录 if(StringUtils.isBlank(_remotePath)){ _remotePath=remotePath; } ftpClient.changeWorkingDirectory(_remotePath); FTPFile[] ftpFiles = ftpClient.listFiles(); boolean isDelete = false; for (FTPFile file : ftpFiles) { if (fileName.equalsIgnoreCase(file.getName())) { ftpClient.deleteFile(file.getName()); isDelete = true; } } closeClient(ftpClient); return isDelete; } @Override public void closeClient(FTPClient ftpClient) { try { if (ftpClient != null) { ftpClient.logout(); } } catch (Exception e) { e.printStackTrace(); } finally { if (ftpClient != null && ftpClient.isConnected()) { try { ftpClient.disconnect(); } catch (IOException ioe) { ioe.printStackTrace(); } } } } /** * 创建目录(有则切换目录,没有则创建目录) * @param dir * @return */ private boolean createOrChangeDir(String dir){ if(StringUtils.isBlank(dir)) return true; String d; try { //目录编码,解决中文路径问题 d = new String(dir.toString().getBytes("UTF-8"),"iso-8859-1"); //尝试切入目录 if(ftpClient.changeWorkingDirectory(d)) return true; dir = StringUtils.removeStart(dir, "/"); dir = StringUtils.removeEnd(dir, "/"); String[] arr = dir.split("/"); StringBuffer sbfDir=new StringBuffer(); //循环生成子目录 for(String s : arr){ sbfDir.append("/"); sbfDir.append(s); //目录编码,解决中文路径问题 d = new String(sbfDir.toString().getBytes("UTF-8"),"iso-8859-1"); //尝试切入目录 if(ftpClient.changeWorkingDirectory(d)) continue; if(!ftpClient.makeDirectory(d)){ LOGGER.info("[失败]ftp创建目录:"+sbfDir.toString()); return false; } LOGGER.info("[成功]创建ftp目录:"+sbfDir.toString()); } //将目录切换至指定路径 return ftpClient.changeWorkingDirectory(d); } catch (Exception e) { e.printStackTrace(); return false; } } }
工场类 FTPFactory.java
import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.SocketException; public class FTPFactory { public static final String HANDLE_FTP="ftp"; public static final String HANDLE_SFTP="sftp"; /** * 获取FTPHandler对象,目前只实现了ftp * @param handleName HANDLE_FTP或HANDLE_SFTP * @return */ public static FTPHandler getHandler(String handleName){ FTPHandler handler=null; if(handleName.equals(HANDLE_FTP)){ handler=new FTPHandlerImpl(); } return handler; } public static void main(String[] args) throws SocketException, IOException { FTPHandler handler = getHandler(HANDLE_FTP); boolean connect = handler.connect(); if(connect){ File f=new File("C:\Users\pcdalao\Desktop\definitions.json"); InputStream is=new FileInputStream(f); boolean uploadFile = handler.uploadFile("/upload_case/20170825/测试", "definition_test.json", is); if(uploadFile){ System.out.println("success"); }else{ System.out.println("fail"); } } } }
使用的时候,直接从工程获取即可。
说明:PropertiesUtils这个工具类,有很多可以替代的实现,需要自己实现哦。
就此一个完整的FTP操作完成。记录一下,方便自己,也方便园子里的朋友参考。设计不当之处,请多多指教。