package com.guige.base.fileutils; import com.alibaba.fastjson.annotation.JSONField; import com.guige.base.dto.FileBaseDto; import org.apache.commons.net.PrintCommandListener; import org.apache.commons.net.ftp.*; import java.io.*; import java.nio.file.Path; import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; public class FtpFileUtil extends FileUtil { @JSONField(serialize=false) private final FTPClient ftp =new FTPClient(); private String hostname; private Integer port; private String username; private String password; private int connectCount = 0; private String workPath; public FtpFileUtil(String hostname, Integer port, String username, String password) { this.hostname = hostname; this.port = port; this.username = username; this.password = password; super.getLinkConf().put("HOSTNAME",hostname); super.getLinkConf().put("PORT",port+""); super.getLinkConf().put("USERNAME",username); super.getLinkConf().put("PASSWORD",password); this.ftp.setControlEncoding("UTF-8"); } public int getConnectCount() { return connectCount; } public void setConnectCount(int connectCount) { this.connectCount = connectCount; } /** * 连接 * * @return * @throws IOException */ private boolean connect() throws IOException { if (this.ftp.isConnected()) { setConnectCount(getConnectCount() + 1); // log.info(getConnectCount()+"添加链接 不创建"); this.ftp.changeWorkingDirectory(workPath); return true; } boolean debug = false; if (debug) { // 设置将过程中使用到的命令输出到控制台 this.ftp.addProtocolCommandListener(new PrintCommandListener( new PrintWriter(System.out), true)); } //设置系统类型 final FTPClientConfig config = new FTPClientConfig( FTPClientConfig.SYST_UNIX); this.ftp.configure(config); try { this.ftp.connect(hostname, port); if (!FTPReply.isPositiveCompletion(this.ftp.getReplyCode())) { this.ftp.disconnect(); throw new IOException("FTP server refused connection."); } } catch (IOException e) { if (this.ftp.isConnected()) { try { this.ftp.disconnect(); } catch (IOException f) { throw new IOException("FTP server refused connection."); } } e.printStackTrace(); throw new IOException("FTP server refused connection."); } if (!this.ftp.login(username, password)) { this.ftp.logout(); throw new IOException("Could not login to server."); } setConnectCount(getConnectCount() + 1); // log.info(getConnectCount()+"创建链接"); workPath=this.ftp.printWorkingDirectory(); return true; } /** * 销毁 * * @throws IOException */ private void disconnect() throws IOException { if (this.ftp.isConnected()) { try { if (getConnectCount()-1>=1) { //在链接内部 不关闭 setConnectCount(getConnectCount() - 1); // log.info(getConnectCount()+"在链接内部 不关闭"); } else { this.ftp.logout(); this.ftp.disconnect(); setConnectCount(getConnectCount() - 1); // log.info(getConnectCount()+"关闭FTP链接"); } } catch (IOException f) { } } } /** * 在FTP服务器上创建并转到工作目录 * * @param relativePath 相对工作路径,不包含文件名:如 dd/11/22/33 * @param ftpClient 录创建是否成功 * @return * @throws IOException */ private boolean createDirectory(String relativePath, FTPClient ftpClient) throws IOException { /* if (!relativePath.startsWith("/")) { relativePath = "/" + relativePath; }*/ if (!changeWorkingDirectory(relativePath)) { //目录不存在,则创建各级目录 for (String subDir : relativePath.split("/")) { if (!subDir.equals("")) { String newDir = ftpClient.printWorkingDirectory() + "/" + subDir; ftpClient.mkd(newDir); if (!changeWorkingDirectory(newDir)) { return false; } } } } return true; } @Override public boolean saveFile(String pathStr, String filename, InputStream input, boolean replace_existing) throws IOException { try { connect(); String path = Paths.get(pathStr).toString(); String workPath = this.ftp.printWorkingDirectory(); // 创建并转到工作目录 String absDstDir = path.replace("\\","/"); createDirectory(absDstDir, this.ftp); // 设置各种属性 this.ftp.setFileType(FTP.BINARY_FILE_TYPE); // Use passive mode as default because most of us are behind firewalls these days. this.ftp.enterLocalPassiveMode(); this.ftp.setBufferSize(1024); // 进度监听 FTPFile[] files = this.ftp.listFiles(filename); if (files.length == 1) { if (replace_existing) { if (this.ftp.deleteFile(filename)) { this.ftp.storeFile(filename, input); input.close(); } else { throw new IOException("文件已存在 删除失败"); } } else { throw new IOException("文件已存在"); } } else { this.ftp.storeFile(filename, input); input.close(); } } finally { disconnect(); } return true; } @Override public boolean saveFile(String path, String filename, byte[] fileDate, boolean replace_existing) throws IOException { InputStream input = new ByteArrayInputStream(fileDate); return saveFile(path, filename, input, replace_existing); } @Override public boolean saveFile(String path, String filename, String base64Data, boolean replace_existing) throws IOException { byte[] fileDate = com.sun.org.apache.xerces.internal.impl.dv.util.Base64.decode(base64Data); return saveFile(path, filename, fileDate, replace_existing); } @Override public boolean saveFile(String path, String filename, File file, boolean replace_existing) throws IOException { InputStream input = new FileInputStream(file); return saveFile(path, filename, input, replace_existing); } @Override public boolean saveFile(String path, File file, boolean replace_existing) throws IOException { InputStream input = new FileInputStream(file); return saveFile(path, file.getName(), input, replace_existing); } @Override public boolean saveFile(String path, List<File> files, boolean replace_existing) throws IOException { try { connect(); for (File file : files) { saveFile(path, file, replace_existing); } }finally { disconnect(); } return true; } @Override public boolean saveLocalFile(String path, List<String> urls, boolean replace_existing) throws IOException { try { // log.info("---开启"); connect(); for (String url : urls) { saveFile(path, new File(url), replace_existing); } }finally { // log.info("---关闭"); disconnect(); } return true; } @Override public InputStream readInputStream(String pathStr, String filename) throws IOException { try { connect(); this.ftp.enterLocalPassiveMode(); if (!changeWorkingDirectory(pathStr)) { return null; }else{ return this.ftp.retrieveFileStream(filename); } } catch (Exception e) { e.printStackTrace(); throw new IOException("下载失败." + e.getMessage()); } finally { disconnect(); } } @Override public List<FileBaseDto> readFileList(String pathStr, boolean isReadDir) throws IOException { List<FileBaseDto> list = new ArrayList<>(); try { connect(); pathStr = Paths.get(pathStr).toString(); pathStr.replace("\\", "/"); list.addAll(readFileList(pathStr, isReadDir, this.ftp)); System.out.println(list.size()); return list; } catch (Exception e){ e.printStackTrace(); }finally { System.out.println(list.size()); disconnect(); } return list; } @Override public FileBaseDto readFileInfo(String path, String filename) throws IOException { FileBaseDto fileBaseDto = null; try { connect(); String pathStr = Paths.get(path,filename).toString(); pathStr.replace("\\", "/"); List<FileBaseDto> list = readFileList(pathStr, false, this.ftp); if(list !=null&&list.size()!=0){ fileBaseDto= list.get(0); } } finally { disconnect(); } return fileBaseDto; } private List<FileBaseDto> readFileList(String pathStr, boolean isReadDir, FTPClient ftpClient) throws IOException { List<FileBaseDto> fileBaseDtos = new ArrayList<>(); try { connect(); // Use passive mode as default because most of us are behind firewalls these days. this.ftp.enterLocalPassiveMode(); Path path = Paths.get(pathStr); Path filePath = null; if (pathStr.contains(".")) { filePath = path.getParent(); } else { filePath = path; } if (!changeWorkingDirectory(filePath.toString())) { return fileBaseDtos; } else { FTPFile[] files = null; if (pathStr.contains(".")) { files = ftpClient.listFiles(path.getFileName().toString()); } else { files = ftpClient.listFiles(); } if (files != null && files.length > 0) { for (FTPFile ftpFile : files) { FileBaseDto fileBaseDto = new FileBaseDto(); fileBaseDto.setContentType(getContentType(ftpFile.getName().toString())); fileBaseDto.setOriginName(ftpFile.getName().toString()); fileBaseDto.setFilePath(filePath.toString()); fileBaseDto.setFileSize(ftpFile.getSize()); fileBaseDto.setStorageType(2); if (ftpFile.isFile()) { fileBaseDtos.add(fileBaseDto); } else if (ftpFile.isDirectory()) { if (isReadDir) { fileBaseDtos.add(fileBaseDto); } fileBaseDtos.addAll(readFileList(filePath.resolve(ftpFile.getName()).toString(), isReadDir,ftpClient)); } } } } } catch (Exception e) { e.printStackTrace(); throw new IOException( e.getMessage()); } finally { disconnect(); } return fileBaseDtos; } @Override public boolean delete(String pathName) throws IOException { try { connect(); if(!pathName.contains(workPath)) { pathName = Paths.get(workPath, pathName).toString(); } pathName = pathName.replace("\\", "/"); if(pathName.contains(".")){ if (!ftp.deleteFile(pathName)){ return false; }else{ return true; } } List<FileBaseDto> list = readFileList(pathName, true); if(list.size()<1){ return false; } for(FileBaseDto fileBaseDto:list){ if(fileBaseDto.getContentType().equals("dir")){ delete(fileBaseDto.getFilePath()); }else{ ftp.deleteFile(Paths.get(fileBaseDto.getFilePath(),fileBaseDto.getOriginName()).toString().replace("\\","/")); } } // 切换到父目录,不然删不掉文件夹 changeWorkingDirectory(Paths.get(pathName).getParent().toString().replace("\\","/")); ftp.removeDirectory(pathName); }catch (Exception e){ e.printStackTrace(); throw new IOException("删除失败"+e.getMessage()); }finally { disconnect(); } return true; } @Override public boolean delete(List<String> paths) throws IOException { try { connect(); for (String path : paths) { try { delete(path); }catch (Exception e){ e.printStackTrace(); } } }catch (Exception e){ e.printStackTrace(); throw new IOException("删除失败"+e.getMessage()); }finally { disconnect(); } return true; } @Override public boolean exists(String path) throws IOException { try { List<FileBaseDto> list = readFileList(path, true); if (list != null && list.size() > 0) { return true; } return false; }catch (Exception e){ e.printStackTrace(); return false; } } @Override public boolean moveTo(String path, String newPath, boolean replace_existing) throws IOException { try { connect(); path=Paths.get(path).toString().replace("\\","/"); newPath=Paths.get(newPath).toString().replace("\\","/"); operateDir(true,path,newPath,replace_existing); }catch (Exception e){ e.printStackTrace(); throw new IOException(e.getMessage()); }finally { disconnect(); } return true; } @Override public boolean copy(String path, String newPath, boolean replace_existing) throws IOException { throw new IOException("复制失败,FTP未实现复制功能,可先下载再上传到其他目录"); } private void operateDir(boolean move, String path, String newPath, boolean replace_existing) throws IOException { if (path.contains(".") && !newPath.contains(".")) { throw new IllegalArgumentException("源文件是文件,目标文件是文件夹"); } else if (!path.contains(".") && newPath.contains(".")) { throw new IllegalArgumentException("目标文件是文件,源文件是文件夹"); } if (newPath.contains(path)) { throw new IllegalArgumentException("目标文件夹不能是源文件夹的子文件夹"); } if(move){ if(!this.ftp.rename(path,newPath)){ //检查文件是否存在 if(exists(newPath)){ if(replace_existing){ delete(newPath); if(exists(newPath)){ delete(newPath); } if(!exists(newPath)){ if(!this.ftp.rename(path,newPath)){ throw new IOException("移动失败,该文件不能覆盖"); } }else{ throw new IOException("移动失败,该文件不能覆盖"); } }else{ throw new IOException("移动失败,该文件已存在"); } } } return; }else{ throw new IOException("复制失败,FTP未实现复制功能,可先下载再上传到其他目录"); } } /** * 复制文件夹. * * @param sourceDir * @param targetDir * @throws IOException */ public void copyDirectiory(String sourceDir, String targetDir,FTPClient ftpClient) throws IOException { // 新建目标目录 if (!exists(targetDir)) { createDirectory(targetDir,ftpClient); } // 获取源文件夹当前下的文件或目录 // File[] fileutils = (new File(sourceDir)).listFiles(); FTPFile[] ftpFiles = ftpClient.listFiles(sourceDir); for (int i = 0; i < ftpFiles.length; i++) { if (ftpFiles[i].isFile()) { copyFile(ftpFiles[i].getName(), sourceDir, targetDir,ftpClient); } else if (ftpFiles[i].isDirectory()) { copyDirectiory(sourceDir + "/" + ftpFiles[i].getName(), targetDir + "/" + ftpFiles[i].getName(),ftpClient); } } } /** * 复制文件. * * @param sourceFileName * @param targetDir * @throws IOException */ public void copyFile(String sourceFileName, String sourceDir, String targetDir,FTPClient ftpClient) throws IOException { InputStream is = null; try { if (!exists(targetDir)) { createDirectory(targetDir,ftpClient); } // 变更工作路径 changeWorkingDirectory(sourceDir); // 设置以二进制流的方式传输 ftpClient.setFileType(FTP.BINARY_FILE_TYPE); is = ftpClient.retrieveFileStream(sourceFileName); // 主动调用一次getReply()把接下来的226消费掉. 这样做是可以解决这个返回null问题 ftpClient.getReply(); if (is != null) { changeWorkingDirectory(targetDir); ftpClient.storeFile(sourceFileName, is); } } finally { // 关闭流 if (is != null) { is.close(); } } } private boolean changeWorkingDirectory(String path) throws IOException { path= Paths.get(path).toString().replace("\\","/"); if(path.contains(workPath)){ return this.ftp.changeWorkingDirectory(path); } this.ftp.changeWorkingDirectory(workPath); path=Paths.get(workPath,path).toString().replace("\\","/"); return this.ftp.changeWorkingDirectory(path); } public FTPClient getFtp() { return ftp; } public String getHostname() { return hostname; } public void setHostname(String hostname) { this.hostname = hostname; } public Integer getPort() { return port; } public void setPort(Integer port) { this.port = port; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPassword() { return password; } public void setPassword(String password) { this.password = password; } public String getWorkPath() { return workPath; } public void setWorkPath(String workPath) { this.workPath = workPath; } }
文件管理存储之FTP存储
猜你喜欢
转载自www.cnblogs.com/songanwei/p/9075147.html
今日推荐
周排行