本文已参与「新人创作礼」活动, 一起开启掘金创作之路。
1.pom文件中引用依赖
<!-- https://mvnrepository.com/artifact/commons-net/commons-net --> <dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.3</version> </dependency><!-- https://mvnrepository.com/artifact/commons-pool/commons-pool --> <dependency> <groupId>commons-pool</groupId> <artifactId>commons-pool</artifactId> <version>1.6</version> </dependency>
- ftp的properties的配置文件
#FTP连接池配置 #最大数 ftpClient_maxTotal=100 #最小空闲 ftpClient_minIdle=10 #最大空闲 ftpClient_maxIdle=100 #最大等待时间 ftpClient_maxWait=3000 #池对象耗尽之后是否阻塞,maxWait<0时一直等待 ftpClient_blockWhenExhausted=true #取对象是验证 ftpClient_testOnBorrow=true #回收验证 ftpClient_testOnReturn=true #创建时验证 ftpClient_testOnCreate=true #空闲验证 ftpClient_testWhileIdle=false #后进先出 ftpClient_lifo=false #FTP连接属性配置 #ip #测试 ftpClient_host=192.168.0.208 #端口 ftpClient_port=21 #登录名 #测试 线上 ftpClient_username=admin #密码 #开发 #测试 线上 ftpClient_pasword=sinorock123 #连接是否为主动模式 ftpClient_passiveMode=true #编码 ftpClient_encoding=UTF-8 #超时时间 ftpClient_clientTimeout=6000 #线程数 ftpClient_threaNum=1 #文件传送类型 #0=ASCII_FILE_TYPE(ASCII格式) 1=EBCDIC_FILE_TYPE 2=LOCAL_FILE_TYPE(二进制文件) ftpClient_transferFileType=2 #是否重命名 ftpClient_renameUploaded=true #重新连接时间 ftpClient_retryTimes=1200 #缓存大小 ftpClient_bufferSize=1024 #默认进入的路径 #测试 线上 ftpClient_workingDirectory=/home/admin/
3.FtpConfig文件
package com.lawschool.util.ftp; public class FTPConfig { /** * 主机 */ private String host; /** * 端口 */ private int port; /** * */ private String username; /** * */ private String password; /** * */ private boolean passiveMode; /** * */ private String encoding; private int clientTimeout; private int threadNum; private int transferFileType; private boolean renameUploaded; private int retryTimes; private int bufferSize; private String workingDirectory; public String getWorkingDirectory() { return workingDirectory; } public void setWorkingDirectory(String workingDirectory) { this.workingDirectory = workingDirectory; } public int getBufferSize() { return bufferSize; } public void setBufferSize(int bufferSize) { this.bufferSize = bufferSize; } public String getHost() { return host; } public void setHost(String host) { this.host = host; } public int getPort() { return port; } public void setPort(int 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 boolean getPassiveMode() { return passiveMode; } public void setPassiveMode(boolean passiveMode) { this.passiveMode = passiveMode; } public String getEncoding() { return encoding; } public void setEncoding(String encoding) { this.encoding = encoding; } public int getClientTimeout() { return clientTimeout; } public void setClientTimeout(int clientTimeout) { this.clientTimeout = clientTimeout; } public int getThreadNum() { return threadNum; } public void setThreadNum(int threadNum) { this.threadNum = threadNum; } public int getTransferFileType() { return transferFileType; } public void setTransferFileType(int transferFileType) { this.transferFileType = transferFileType; } public boolean isRenameUploaded() { return renameUploaded; } public void setRenameUploaded(boolean renameUploaded) { this.renameUploaded = renameUploaded; } public int getRetryTimes() { return retryTimes; } public void setRetryTimes(int retryTimes) { this.retryTimes = retryTimes; } }
4. FTPClientPool
package com.lawschool.util.ftp; import java.util.Properties; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.springframework.core.io.Resource; public class FTPClientPool { private GenericObjectPool<FTPClient> ftpClientPool; private Resource configLocation; public Resource getConfigLocation() { return configLocation; } public void setConfigLocation(Resource configLocation) { this.configLocation = configLocation; Properties pro = new Properties(); try { pro.load(configLocation.getInputStream()); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } // 初始化对象池配置 GenericObjectPoolConfig poolConfig = new GenericObjectPoolConfig(); poolConfig.setBlockWhenExhausted(Boolean.parseBoolean(pro.getProperty("ftpClient_blockWhenExhausted"))); poolConfig.setMaxWaitMillis(Long.parseLong(pro.getProperty("ftpClient_maxWait"))); poolConfig.setMinIdle(Integer.parseInt(pro.getProperty("ftpClient_minIdle"))); poolConfig.setMaxIdle(Integer.parseInt(pro.getProperty("ftpClient_maxIdle"))); poolConfig.setMaxTotal(Integer.parseInt(pro.getProperty("ftpClient_maxTotal"))); poolConfig.setTestOnBorrow(Boolean.parseBoolean(pro.getProperty("ftpClient_testOnBorrow"))); poolConfig.setTestOnReturn(Boolean.parseBoolean(pro.getProperty("ftpClient_testOnReturn"))); poolConfig.setTestOnCreate(Boolean.parseBoolean(pro.getProperty("ftpClient_testOnCreate"))); poolConfig.setTestWhileIdle(Boolean.parseBoolean(pro.getProperty("ftpClient_testWhileIdle"))); poolConfig.setLifo(Boolean.parseBoolean(pro.getProperty("ftpClient_lifo"))); FTPConfig ftpConfig = new FTPConfig(); ftpConfig.setHost(pro.getProperty("ftpClient_host")); ftpConfig.setPort(Integer.parseInt(pro.getProperty("ftpClient_port"))); ftpConfig.setUsername(pro.getProperty("ftpClient_username")); ftpConfig.setPassword(pro.getProperty("ftpClient_pasword")); ftpConfig.setClientTimeout(Integer.parseInt(pro.getProperty("ftpClient_clientTimeout"))); ftpConfig.setEncoding(pro.getProperty("ftpClient_encoding")); ftpConfig.setWorkingDirectory(pro.getProperty("ftpClient_workingDirectory")); ftpConfig.setPassiveMode(Boolean.parseBoolean(pro.getProperty("ftpClient_passiveMode"))); ftpConfig.setRenameUploaded(Boolean.parseBoolean(pro.getProperty("ftpClient_renameUploaded"))); ftpConfig.setRetryTimes(Integer.parseInt(pro.getProperty("ftpClient_retryTimes"))); ftpConfig.setTransferFileType(Integer.parseInt(pro.getProperty("ftpClient_transferFileType"))); ftpConfig.setBufferSize(Integer.parseInt(pro.getProperty("ftpClient_bufferSize"))); // 初始化对象池 ftpClientPool = new GenericObjectPool<FTPClient>(new FTPClientFactory(ftpConfig), poolConfig); } public FTPClientPool() { } public GenericObjectPool<FTPClient> getFtpClientPool() { return ftpClientPool; } public FTPClientPool(Resource configLocation) { } public FTPClient borrowObject() throws Exception { return ftpClientPool.borrowObject(); } public void returnObject(FTPClient ftpClient) { ftpClientPool.returnObject(ftpClient); } }
5.FTPClientFactory
package com.lawschool.util.ftp; import java.io.IOException; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPReply; import org.apache.commons.pool2.BasePooledObjectFactory; import org.apache.commons.pool2.PooledObject; import org.apache.commons.pool2.impl.DefaultPooledObject; import org.apache.log4j.Logger; public class FTPClientFactory extends BasePooledObjectFactory<FTPClient>{ private static Logger logger = Logger.getLogger(FTPClientFactory.class); private FTPConfig ftpConfig; public FTPClientFactory(FTPConfig ftpConfig) { this.ftpConfig = ftpConfig; } /** * 新建对象 */ @Override public FTPClient create() throws Exception { FTPClient ftpClient = new FTPClient(); ftpClient.setConnectTimeout(ftpConfig.getClientTimeout()); try { ftpClient.connect(ftpConfig.getHost(), ftpConfig.getPort()); int reply = ftpClient.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { ftpClient.disconnect(); logger.error("FTPServer 拒绝连接"); return null; } boolean result = ftpClient.login(ftpConfig.getUsername(), ftpConfig.getPassword()); if (!result) { logger.error("ftpClient登陆失败!"); throw new Exception("ftpClient登陆失败! userName:" + ftpConfig.getUsername() + " ; password:" + ftpConfig.getPassword()); } ftpClient.setFileType(ftpConfig.getTransferFileType()); ftpClient.setBufferSize(ftpConfig.getBufferSize()); ftpClient.setControlEncoding(ftpConfig.getEncoding()); if (ftpConfig.getPassiveMode()) { ftpClient.enterLocalPassiveMode(); } ftpClient.changeWorkingDirectory(ftpConfig.getWorkingDirectory()); } catch (IOException e) { logger.error("FTP连接失败:", e); } return ftpClient; } @Override public PooledObject<FTPClient> wrap(FTPClient ftpClient) { return new DefaultPooledObject<FTPClient>(ftpClient); } /** * 销毁对象 */ @Override public void destroyObject(PooledObject<FTPClient> p) throws Exception { FTPClient ftpClient = p.getObject(); ftpClient.logout(); super.destroyObject(p); } /** * 验证对象 */ @Override public boolean validateObject(PooledObject<FTPClient> p) { FTPClient ftpClient = p.getObject(); boolean connect = false; try { connect = ftpClient.sendNoOp(); if (connect) { ftpClient.changeWorkingDirectory(ftpConfig.getWorkingDirectory()); } } catch (IOException e) { e.printStackTrace(); } return connect; } }
- FtpUtil
package com.lawschool.util; import com.lawschool.beans.accessory.AccessoryEntity; import com.lawschool.service.accessory.AccessoryService; import com.lawschool.util.ftp.FTPClientPool; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import org.springframework.web.context.ContextLoaderListener; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.text.SimpleDateFormat; import java.util.Date; @Component public class FileUtil { private static Logger logger = LoggerFactory.getLogger(FileUtil.class); /** * @return com.lawschool.util.Result * @Author MengyuWu * @Description 上传文件 * @Date 19:23 2018-12-19 * @Param [filename, input] **/ public static Result uploadToFTPServer(String filename, InputStream input) { Result result = new Result(); FTPClientPool ftpClientPool = (FTPClientPool) SpringContextUtils.getBean("ftpClientPool"); FTPClient ftpClient = null; try { ftpClient = ftpClientPool.borrowObject(); //根据文件名截取相关的文件类型 int start = filename.lastIndexOf("."); String type = filename.substring(start + 1, filename.length());//后缀名 //获取附件servcie AccessoryService accessoryService = SpringContextUtils.getBean("accessoryService", AccessoryService.class); //AccessoryService accessoryService =(AccessoryService)ContextLoaderListener.getCurrentWebApplicationContext().getBean ("accessoryService"); AccessoryEntity accessoryEntity = new AccessoryEntity(); accessoryEntity.setId(GetUUID.getUUIDs("AE"));//设置id accessoryEntity.setAccessoryName(filename);//设置文件名 accessoryEntity.setAccessoryType(type);//设置文件类型 System.out.println("开始上传文件"); //inputStream = new FileInputStream(new File(originfilename)); //initFtpClient(); ftpClient.setFileType(ftpClient.BINARY_FILE_TYPE); String curDate = new SimpleDateFormat("yyyyMMdd").format(new Date()); //CreateDirecroty(curDate); ftpClient.makeDirectory(curDate); ftpClient.changeWorkingDirectory(curDate); ftpClient.storeFile(accessoryEntity.getId() + "." + type, input); input.close(); //不需要退出 要不然返回到ftp连接池就会报错啦 //ftpClient.logout(); String filePath = curDate; accessoryEntity.setFilePath(filePath);//设置文件路径 accessoryService.insert(accessoryEntity);//保存文件信息 result.put("accessoryId", accessoryEntity.getId()); System.out.println("上传文件成功"); } catch (Exception e) { System.out.println("上传文件失败"); e.printStackTrace(); return Result.error("上传文件失败"); } finally { ftpClientPool.returnObject(ftpClient); if (null != input) { try { input.close(); } catch (IOException e) { e.printStackTrace(); } } } return result; } /** * @return boolean * @Author MengyuWu * @Description 改变目录路径 * @Date 19:41 2018-12-19 * @Param [directory] **/ public static boolean changeWorkingDirectory(String directory, FTPClient ftpClient) { boolean flag = true; try { flag = ftpClient.changeWorkingDirectory(directory); if (flag) { System.out.println("进入文件夹" + directory + " 成功!"); } else { System.out.println("进入文件夹" + directory + " 失败!开始创建文件夹"); } } catch (IOException ioe) { ioe.printStackTrace(); } return flag; } /** * @return * @Author MengyuWu * @Description 创建多层目录文件,如果有ftp服务器已存在该文件,则不创建,如果无,则创建 * @Date 19:42 2018-12-19 * @Param **/ public static boolean CreateDirecroty(String remote, FTPClient ftpClient) throws IOException { boolean success = true; String directory = remote + "/"; // 如果远程目录不存在,则递归创建远程服务器目录 if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(new String(directory), ftpClient)) { int start = 0; int end = 0; if (directory.startsWith("/")) { start = 1; } else { start = 0; } end = directory.indexOf("/", start); String path = ""; String paths = ""; while (true) { String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1"); path = path + "/" + subDirectory; if (!existFile(path, ftpClient)) { if (makeDirectory(subDirectory, ftpClient)) { changeWorkingDirectory(subDirectory, ftpClient); } else { System.out.println("创建目录[" + subDirectory + "]失败"); changeWorkingDirectory(subDirectory, ftpClient); } } else { changeWorkingDirectory(subDirectory, ftpClient); } paths = paths + "/" + subDirectory; start = end + 1; end = directory.indexOf("/", start); // 检查所有目录是否创建完毕 if (end <= start) { break; } } } return success; } /** * @return boolean * @Author MengyuWu * @Description 判断ftp服务器文件是否存在 * @Date 19:42 2018-12-19 * @Param [path] **/ public static boolean existFile(String path, FTPClient ftpClient) throws IOException { boolean flag = false; FTPFile[] ftpFileArr = ftpClient.listFiles(path); if (ftpFileArr.length > 0) { flag = true; } return flag; } /** * @return boolean * @Author MengyuWu * @Description 创建目录 * @Date 19:42 2018-12-19 * @Param [dir] **/ public static boolean makeDirectory(String dir, FTPClient ftpClient) { boolean flag = true; try { flag = ftpClient.makeDirectory(dir); if (flag) { System.out.println("创建文件夹" + dir + " 成功!"); } else { System.out.println("创建文件夹" + dir + " 失败!"); } } catch (Exception e) { e.printStackTrace(); } return flag; } /** * @return void * @Author MengyuWu * @Description 下载文件 * @Date 19:42 2018-12-19 * @Param [accessoryId, outputStream] **/ public static OutputStream downloadFromFileServer(String accessoryId, OutputStream outputStream) { //获取附件servcie AccessoryService accessoryService = SpringContextUtils.getBean("accessoryService", AccessoryService.class); //根据附件id下载相关的附件 AccessoryEntity accessoryEntity = accessoryService.selectById(accessoryId); if (UtilValidate.isEmpty(accessoryEntity)) { logger.info("文件不存在"); } FTPClientPool ftpClientPool = (FTPClientPool) SpringContextUtils.getBean("ftpClientPool"); FTPClient ftpClient = null; try { ftpClient = ftpClientPool.borrowObject(); System.out.println("开始下载文件"); //切换FTP对应的文件目录 boolean test = ftpClient.changeWorkingDirectory(accessoryEntity.getFilePath()); //每次数据连接之前,ftp client告诉ftp server开通一个端口来传输数据。 ftpClient.enterLocalPassiveMode(); FTPFile[] ftpFiles = ftpClient.listFiles(); for (FTPFile file : ftpFiles) { if (file.getName().equals(accessoryEntity.getId() + "." + accessoryEntity.getAccessoryType())) { ftpClient.retrieveFile(file.getName(), outputStream); outputStream.close(); } } //不需要退出 要不然返回到ftp连接池就会报错啦 //ftpClient.logout(); System.out.println("下载文件成功"); } catch (Exception e) { System.out.println("下载文件失败"); e.printStackTrace(); } finally { ftpClientPool.returnObject(ftpClient); if (null != outputStream) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return outputStream; } /** * @Author MengyuWu * @Description 删除文件 * @Date 19:43 2018-12-19 * @Param [pathname, filename] * @return boolean **/ public boolean deleteFile(String pathname, String filename){ boolean flag = false; FTPClientPool ftpClientPool = (FTPClientPool) SpringContextUtils.getBean("ftpClientPool"); FTPClient ftpClient = null; try { System.out.println("开始删除文件"); ftpClient = ftpClientPool.borrowObject(); //切换FTP目录 ftpClient.changeWorkingDirectory(pathname); ftpClient.dele(filename); //ftpClient.logout(); flag = true; System.out.println("删除文件成功"); } catch (Exception e) { System.out.println("删除文件失败"); e.printStackTrace(); } finally { ftpClientPool.returnObject(ftpClient); } return flag; } }
6.SysCommonController
package com.lawschool.controller.system; import com.baomidou.mybatisplus.mapper.EntityWrapper; import com.lawschool.base.AbstractController; import com.lawschool.beans.User; import com.lawschool.beans.accessory.AccessoryEntity; import com.lawschool.beans.system.SysMenuEntity; import com.lawschool.service.UserService; import com.lawschool.service.accessory.AccessoryService; import com.lawschool.util.FileUtil; import com.lawschool.util.Result; import com.lawschool.util.UtilValidate; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import javax.servlet.ServletOutputStream; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; /** * ClassName: SysCommonController * Description: 系统公共的controller * date: 2018-12-6 13:48 * * @author MengyuWu * @since JDK 1.8 */ @Controller @RequestMapping("/sys") public class SysCommonController extends AbstractController { @Autowired private AccessoryService accessoryService; @Autowired private UserService userService; /** * @Author MengyuWu * @Description 系统文件上传 * @Date 14:13 2018-12-6 * @Param [request] * @return com.lawschool.util.Result **/ @ResponseBody @RequestMapping(value = "/upload", method = RequestMethod.POST) public Result upload(MultipartHttpServletRequest request) throws IOException { Result result = new Result(); List<MultipartFile> importfile = request.getFiles("importfile"); if (UtilValidate.isEmpty(importfile)) { throw new RuntimeException("上传失败:文件为空"); } for (MultipartFile multipartFile : importfile) { //获取文件名 String originalFilename = multipartFile.getOriginalFilename(); if (originalFilename.contains(",")) { originalFilename = originalFilename.replaceAll(",", ""); } InputStream inputStream = multipartFile.getInputStream();//输入流 Result uploadResult = FileUtil.uploadToFTPServer(originalFilename,inputStream); if("success".equals(uploadResult.get("msg"))){ return uploadResult; }else{ return result.error("上传失败"); } } return result.error("未知异常"); } /** * @Author MengyuWu * @Description 附件下载 * @Date 14:13 2018-12-6 * @Param [filePath, filename, response] * @return void **/ /*@RequestMapping("/download") public void downLoad(@RequestParam(value = "accessoryId") String accessoryId, HttpServletResponse response) throws IOException { if (UtilValidate.isEmpty(accessoryId)) { throw new RuntimeException("文件路径错误"); } //根据附件id下载相关的附件 AccessoryEntity accessoryEntity = accessoryService.selectById(accessoryId); if(UtilValidate.isEmpty(accessoryEntity)){ logger.info("文件不存在"); } ServletOutputStream outputStream = response.getOutputStream(); response=FileUtil.downloadFromFileServer(accessoryId,outputStream,response); outputStream.close(); }*/ @RequestMapping("/download") public void downLoad(@RequestParam String accessoryId, HttpServletResponse response) throws IOException { if (UtilValidate.isEmpty(accessoryId)) { throw new RuntimeException("附件id为空"); } ServletOutputStream outputStream = response.getOutputStream(); AccessoryEntity accessoryEntity = accessoryService.selectOne(new EntityWrapper<AccessoryEntity>().eq("id", accessoryId)); if (UtilValidate.isNotEmpty(accessoryEntity)) { String fileName = null; if (UtilValidate.isNotEmpty(accessoryEntity.getAccessoryName())) { fileName = java.net.URLEncoder.encode(accessoryEntity.getAccessoryName(), "UTF-8"); } else { fileName = "未知名称的附件"; } if (fileName.contains(",")) { fileName = fileName.replaceAll(",", ""); } response.setHeader("Content-Disposition", "attachment; filename=" + fileName); outputStream=(ServletOutputStream)FileUtil.downloadFromFileServer(accessoryId,outputStream); } outputStream.close(); } }