package io.platform.utils; import cn.hutool.core.img.ImgUtil; import cn.hutool.core.io.FileUtil; import org.apache.commons.lang.StringUtils; import org.apache.commons.net.ftp.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.awt.*; import java.io.*; import java.net.SocketException; import java.util.regex.Pattern; /** * Created by chen on 2017/12/27. */ @Component public class FtpUtils { @Value("${ftp.userName}") private String userName; //登录名 @Value("${ftp.password}") private String password; //密码 @Value("${ftp.ftpHostName}") private String ftpHostName; //ftp地址 @Value("${ftp.port}") private int port; //端口 @Value("${ftp.rootPath}") private String rootPath; // upload/admin/ @Value("${ftp.httpAddr}") private String httpAddr; // http://117.50.20.112/upload/ @Value("${ftp.tempDir}") private String tempDir; private FTPClient ftpClient = new FTPClient(); private OutputStream os = null; private InputStream is = null; private Logger logger = LoggerFactory.getLogger(getClass()); private Pattern pattern = Pattern.compile("\\d{8}"); //8位数字 /** * 建立链接 */ private void connect() { try { logger.info("开始链接..." + ftpHostName +"..."+ port); ftpClient.connect(ftpHostName, port); int reply = ftpClient.getReplyCode(); //ftp响应码 logger.error("ftp响应状态码"+reply); if (!FTPReply.isPositiveCompletion(reply)) { //ftp拒绝链接 logger.error("ftp拒绝链接..."); ftpClient.disconnect(); } ftpClient.login(userName, password); ftpClient.enterLocalPassiveMode(); //设置被动模式 通知server端开通端口传输数据 ftpClient.setBufferSize(256); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); ftpClient.setControlEncoding("utf-8"); logger.info("登录成功!"); } catch (SocketException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } } /** * 退出FTP登录关闭链接 并 关闭输入输出流 * * @param */ private void close() { try { if (is != null) { is.close(); } if (os != null) { os.flush(); os.close(); } ftpClient.logout(); logger.info("退出登录!"); ftpClient.disconnect(); logger.info("关闭链接!"); } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } } /** * 判断是否是目录 * * @param fileName * @return */ public boolean isDir(String fileName) { try { // 切换目录,若当前是目录则返回true,否则返回true。 boolean falg = ftpClient.changeWorkingDirectory(fileName); return falg; } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } return false; } /** * 上传文件 * * @param exPath 自定义目录,默认空 * @param extName 文件后缀名 * @param in 文件输入流 */ public String defaultUpload(String exPath, String extName, FileInputStream in) { connect(); String ftpPath; if (StringUtils.isNotEmpty(exPath)) { ftpPath = rootPath + exPath; } else { ftpPath = rootPath; } String fileName = IdUtil.createIdByTime() + "." + extName; boolean flag = uploadFileByDo(ftpPath, fileName, in); close(); String url = null; if (flag) { url = httpAddr + ftpPath + "/" + fileName; } return url; } /** * 上传文件 * * @param ftpPath * @param fileName */ public boolean uploadFile(String ftpPath, String fileName, InputStream is) { connect(); boolean flag = uploadFileByDo(ftpPath, fileName, is); close(); return flag; } /** * 下载文件 * * @param remoteFtpPath * @param localPath * @param fileName * @return */ public boolean downloadFile(String remoteFtpPath, String localPath, String fileName) { connect(); boolean flag = this.downloadFileByDo(remoteFtpPath, localPath, fileName); close(); return flag; } /** * 删除ftp上的文件 * * @param ftpFileName * @return true || false */ public boolean removeFile(String ftpFileName) { boolean flag = false; logger.info("待删除文件:{0}" , ftpFileName); try { ftpFileName = new String(ftpFileName.getBytes("GBK"), "iso-8859-1"); flag = ftpClient.deleteFile(ftpFileName); logger.info("删除文件:[{0}]" , flag ? "成功" : "失败"); return flag; } catch (IOException e) { e.printStackTrace(); return false; } } /** * 删除空目录 * * @param dir * @return */ public boolean removeDir(String dir) { if (StringUtils.startsWith(dir, "/")) dir = "/" + dir; try { String d = new String(dir.toString().getBytes("GBK"), "iso-8859-1"); return ftpClient.removeDirectory(d); } catch (Exception e) { e.printStackTrace(); return false; } } /** * 创建目录(有则切换目录,没有则创建目录) * * @param dir * @return */ public boolean createDir(String dir) { if (StringUtils.isBlank(dir)) return true; String d; try { //目录编码,解决中文路径问题 d = new String(dir.toString().getBytes("GBK"), "iso-8859-1"); //尝试切入目录 if (ftpClient.changeWorkingDirectory(d)) return true; String[] arr = dir.split("/"); StringBuffer sbfDir = new StringBuffer(); //循环生成子目录 for (String s : arr) { sbfDir.append("/"); sbfDir.append(s); //目录编码,解决中文路径问题 d = new String(sbfDir.toString().getBytes("GBK"), "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; } } /** * 上传文件 * * @param ftpPath FTP服务器保存目录 * @param fileName 上传到FTP服务器上的文件名 */ private boolean uploadFileByDo(String ftpPath, String fileName, InputStream is) { try { if (!createDir(ftpPath)) { throw new RuntimeException("切入FTP目录失败:" + ftpPath); } ftpClient.setBufferSize(1024); //解决上传中文 txt 文件乱码 ftpClient.setControlEncoding("utf-8"); FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT); conf.setServerLanguageCode("zh"); // 设置文件类型(二进制) ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); if (ftpClient.storeFile(fileName, is)) { is.close(); return true; } else { logger.info("上传文件失败!"); return false; } } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); return false; } finally { try { if (is != null) { is.close(); } } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } } } /** * 下载文件 * * @param remoteFtpPath FTP服务器保存目录 * localPath * @param fileName 上传到FTP服务器上的文件名 */ private boolean downloadFileByDo(String remoteFtpPath, String localPath, String fileName) { try { boolean changedir = ftpClient.changeWorkingDirectory(remoteFtpPath); if (!changedir) { logger.info("切入目录失败!"); return false; } ftpClient.setBufferSize(1024); //解决上传中文 txt 文件乱码 ftpClient.setControlEncoding("utf-8"); FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT); conf.setServerLanguageCode("zh"); // 设置文件类型(二进制) ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); FTPFile[] files = ftpClient.listFiles(); for (int i = 0; i < files.length; i++) { try { if (fileName.equals(files[i].getName())) { downloadFile(files[i], localPath, remoteFtpPath); return true; } } catch (Exception e) { logger.error("下载异常", e); logger.error("<" + files[i].getName() + ">下载失败"); } } } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); return false; } finally { try { if (is != null) { is.close(); } } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } } return true; } /** * 下载FTP文件 * 当你需要下载FTP文件的时候,调用此方法 * 根据获取的文件名,本地地址,远程地址进行下载 * * @param ftpFile * @param relativeLocalPath * @param relativeRemotePath */ private void downloadFile(FTPFile ftpFile, String relativeLocalPath, String relativeRemotePath) { if (ftpFile.isFile()) { if (ftpFile.getName().indexOf("?") == -1) { OutputStream outputStream = null; try { File entryDir = new File(relativeLocalPath); //如果文件夹路径不存在,则创建文件夹 if (!entryDir.exists() || !entryDir.isDirectory()) { entryDir.mkdirs(); } File locaFile = new File(relativeLocalPath + ftpFile.getName()); //判断文件是否存在,存在则返回 if (locaFile.exists()) { return; } else { outputStream = new FileOutputStream(relativeLocalPath + ftpFile.getName()); ftpClient.retrieveFile(ftpFile.getName(), outputStream); outputStream.flush(); outputStream.close(); } } catch (Exception e) { logger.error("下载异常", e); } finally { try { if (outputStream != null) { outputStream.close(); } } catch (IOException e) { logger.error("输出文件流异常"); } } } } else { String newlocalRelatePath = relativeLocalPath + ftpFile.getName(); String newRemote = new String(relativeRemotePath + ftpFile.getName().toString()); File fl = new File(newlocalRelatePath); if (!fl.exists()) { fl.mkdirs(); } try { newlocalRelatePath = newlocalRelatePath + '/'; newRemote = newRemote + "/"; String currentWorkDir = ftpFile.getName().toString(); boolean changedir = ftpClient.changeWorkingDirectory(currentWorkDir); if (changedir) { FTPFile[] files = null; files = ftpClient.listFiles(); for (int i = 0; i < files.length; i++) { downloadFile(files[i], newlocalRelatePath, newRemote); } } if (changedir) { ftpClient.changeToParentDirectory(); } } catch (Exception e) { logger.error("下载异常", e); } } } /** * 下载文件 * * @param remoteFtpPath FTP服务器保存目录 * localPath * @param fileName 上传到FTP服务器上的文件名 */ public File getFtpFile(String remoteFtpPath, String fileName) { connect(); File file = null; try { boolean changedir = ftpClient.changeWorkingDirectory(remoteFtpPath); if (!changedir) { logger.info("切入目录失败!"); return file; } ftpClient.setBufferSize(1024); //解决上传中文 txt 文件乱码 ftpClient.setControlEncoding("utf-8"); FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT); conf.setServerLanguageCode("zh"); // 设置文件类型(二进制) ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); FTPFile[] files = ftpClient.listFiles(); for (int i = 0; i < files.length; i++) { try { if (fileName.equals(files[i].getName())) { InputStream fis = ftpClient.retrieveFileStream(files[i].getName()); file = new File("drtext.xlsx"); OutputStream os = new FileOutputStream(file); int bytesRead = 0; byte[] buffer = new byte[1024]; while ((bytesRead = fis.read(buffer, 0, 1024)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); fis.close(); return file; } } catch (Exception e) { logger.error("读取异常", e); } } close(); } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } finally { try { if (is != null) { is.close(); } } catch (IOException e) { // TODO Auto-generated catch block logger.error(e.getMessage(), e); } } return file; } 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 getFtpHostName() { return ftpHostName; } public void setFtpHostName(String ftpHostName) { this.ftpHostName = ftpHostName; } public int getPort() { return port; } public void setPort(int port) { this.port = port; } public OutputStream getOs() { return os; } public void setOs(OutputStream os) { this.os = os; } /*public String uploadImage(String extPath, String extName, FileInputStream ins) { connect(); String ftpPath; if (StringUtils.isNotEmpty(extPath)) { ftpPath = rootPath + extPath; } else { ftpPath = rootPath; } String fileName = IdUtil.createIdByTime() + "." + extName; boolean flag = uploadFileByDo(ftpPath, fileName, ins); close(); String url = null; if (flag) { url = httpAddr + ftpPath + fileName; //FileUtil.del(tempFile); } return url; } catch (IOException e) { e.printStackTrace(); return null; } }*/ /** * 测试文件上传 * 1.原目标文件流 * 2.目标文件流 */ public String uploadImage(String extPath, String extName, File file) throws FileNotFoundException { connect(); String ftpPath; if (StringUtils.isNotEmpty(extPath)) { ftpPath = rootPath + extPath; } else { ftpPath = rootPath; } System.out.println(file.length()); FileInputStream ins = new FileInputStream(file); String fileName = IdUtil.createIdByTime() + "." + extName; File tempFile = FileUtil.writeFromStream(ins, tempDir + "/" + fileName); BufferedOutputStream out = FileUtil.getOutputStream(tempFile); try { //TODO 打水印 ImgUtil.pressText( file, // tempFile, "赛轮版权所有", Color.WHITE, //文字 new Font("黑体", Font.BOLD, 50), //字体 0, //x坐标修正值。 默认在中间,偏移量相对于中间偏移 0, //y坐标修正值。 默认在中间,偏移量相对于中间偏移 0.5f//透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 ); //System.out.println(tempFile.length()); boolean flag = uploadFileByDo(ftpPath, fileName, new FileInputStream(tempFile)); close(); String url = null; if (flag) { url = httpAddr + ftpPath + fileName; FileUtil.del(tempFile); //this.deleteAllFilesOfDir(tempFile); } return url; } catch (IOException e) { e.printStackTrace(); return null; } } public String uploadImageForStram(String extPath, String extName, InputStream inputStream) throws FileNotFoundException { connect(); String ftpPath; if (StringUtils.isNotEmpty(extPath)) { ftpPath = rootPath + extPath; } else { ftpPath = rootPath; } String fileName = IdUtil.createIdByTime() + "." + extName; File tempFile = FileUtil.writeFromStream(inputStream, tempDir + "/" + fileName); BufferedOutputStream out = FileUtil.getOutputStream(tempFile); try { //TODO 打水印 ImgUtil.pressText( inputStream, // out, "赛轮版权所有", Color.WHITE, //文字 new Font("黑体", Font.BOLD, 50), //字体 0, //x坐标修正值。 默认在中间,偏移量相对于中间偏移 0, //y坐标修正值。 默认在中间,偏移量相对于中间偏移 0.5f//透明度:alpha 必须是范围 [0.0, 1.0] 之内(包含边界值)的一个浮点数字 ); //System.out.println(tempFile.length()); boolean flag = uploadFileByDo(ftpPath, fileName, new FileInputStream(tempFile)); close(); String url = null; if (flag) { url = httpAddr + ftpPath + fileName; FileUtil.del(tempFile); //FileUtil.del(tempFile); //this.deleteAllFilesOfDir(tempFile); } return url; } catch (IOException e) { e.printStackTrace(); return null; } } public static void deleteAllFilesOfDir(File path) { if (null != path) { if (!path.exists()) return; if (path.isFile()) { boolean result = path.delete(); int tryCount = 0; while (!result && tryCount++ < 10) { System.gc(); // 回收资源 result = path.delete(); } } File[] files = path.listFiles(); if (null != files) { for (int i = 0; i < files.length; i++) { deleteAllFilesOfDir(files[i]); } } path.delete(); } } }