今日分享
每天分享技术实战干货ftp系统设计与实现源码,技术在于积累和收藏ftp系统设计与实现源码,希望可以帮助到您。
架构开源地址:https://gitee.com/msxy
实现方案ftpserver支持配置文件和db两种方式来保存账号信息和其它相关配置,如果我们的业务系统需要将用户信息和ftp的账号信息打通,并且还有相关的业务统计,比如统计系统中每个人上传文件的时间、个数等等,那么使用数据库来保存ftp账号信息还是比较方便灵活的。我这里就选择使用mysqlftp系统设计与实现源码了。
springboot开始整合添加项目依赖 <dependency> <groupId>org.apache.ftpserver</groupId> <artifactId>ftpserver-core</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.apache.ftpserver</groupId> <artifactId>ftplet-api</artifactId> <version>1.1.1</version> </dependency> <dependency> <groupId>org.apache.mina</groupId> <artifactId>mina-core</artifactId> <version>2.0.16</version> </dependency>创建FTP_USER 数据库CREATE TABLE FTP_USER ( userid VARCHAR(64) NOT NULL PRIMARY KEY, userpassword VARCHAR(64), homedirectory VARCHAR(128) NOT NULL, enableflag BOOLEAN DEFAULT TRUE, writepermission BOOLEAN DEFAULT FALSE, idletime INT DEFAULT 0, uploadrate INT DEFAULT 0, downloadrate INT DEFAULT 0, maxloginnumber INT DEFAULT 0, maxloginperip INT DEFAULT 0);字段说明:
userid:登录账号userpassword:登录密码homedirectory:主目录,用户授权主目录enableflag:当前用户可用writepermission:具有上传权限idletime:空闲时间(为300秒)uploadrate:上传速率限制为480000字节每秒 0为不限制downloadrate:下载速率限制为480000字节每秒 0为不限制maxloginnumber:最大登陆用户数maxloginperip:同IP登陆用户数创建Ftpserver类配置ftpserver,提供ftpserver的init()、start()、stop() ***
package com.qingfeng.ftpserver.mysqldatasource;import com.qingfeng.ftpserver.config.YmlProperties;import com.qingfeng.ftpserver.ftplet.MyFtpPlet;import org.apache.ftpserver.ConnectionConfigFactory;import org.apache.ftpserver.DataConnectionConfigurationFactory;import org.apache.ftpserver.FtpServer;import org.apache.ftpserver.FtpServerFactory;import org.apache.ftpserver.ftplet.FtpException;import org.apache.ftpserver.ftplet.Ftplet;import org.apache.ftpserver.listener.ListenerFactory;import org.apache.ftpserver.usermanager.ClearTextPasswordEncryptor;import org.apache.ftpserver.usermanager.DbUserManagerFactory;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.context.annotation.Configuration;import org.springframework.stereotype.Service;import javax.sql.DataSource;import java.io.IOException;import java.util.HashMap;import java.util.Map;/** * @ProjectName MyFtpServer * @author qingfeng * @version 1.0.0 * @Description * 注意:被@Configuration标记的类会被加入ioc容器中,而且类中所有带 @Bean注解的 *** 都会被动态代理,因此调用该 *** 返回的都是同一个实例。 * ftp服务访问地址: * ftp://localhost:2121/ * @createTime 2022/4/21 0021 23:21 */@Configuration("MyFtp")@Servicepublic class MyFtpServer { private static final Logger logger = LoggerFactory.getLogger(MyFtpServer.class); // springboot配置好数据源直接注入即可 private DataSource dataSource; private YmlProperties yml; protected FtpServer server; // 我们这里利用spring加载@Configuration的特性来完成ftp server的初始化 public MyFtpServer(DataSource dataSource, YmlProperties yml) { this.dataSource = dataSource; this.yml = yml; initFtp(); logger.info("Apache ftp server is already instantiation complete!"); System.out.println("Apache ftp server is already instantiation complete!"); } /** * ftp server init * @throws IOException */ public void initFtp() { FtpServerFactory serverFactory = new FtpServerFactory(); ListenerFactory listenerFactory = new ListenerFactory(); // 1、设置服务端口 listenerFactory.setPort(new Integer(this.yml.getFtpport())); // 2、设置被动模式数据上传的接口范围,云服务器需要开放对应区间的端口给客户端 DataConnectionConfigurationFactory dataConnectionConfFactory = new DataConnectionConfigurationFactory(); dataConnectionConfFactory.setPassivePorts(this.yml.getPassiveports()); listenerFactory.setDataConnectionConfiguration(dataConnectionConfFactory.createDataConnectionConfiguration()); // 3、增加SSL安全配置 /* SslConfigurationFactory ssl = new SslConfigurationFactory(); ssl.setKeystoreFile(new File("src/main/resources/ftpserver.jks")); ssl.setKeystorePassword("password"); ssl.setSslProtocol("SSL"); //set the SSL configuration for the listener listenerFactory.setSslConfiguration(ssl.createSslConfiguration()); listenerFactory.setImplicitSsl(true); */ //替换默认的监听器 serverFactory.addListener("default", listenerFactory.createListener()); // 4、设置最大连接数 ConnectionConfigFactory connectionConfigFactory = new ConnectionConfigFactory(); connectionConfigFactory.setMaxLogins(new Integer(this.yml.getMaxlogins())); serverFactory.setConnectionConfig(connectionConfigFactory.createConnectionConfig()); // 5、配置自定义用户事件 Map<String, Ftplet> ftpLets = new HashMap<String, Ftplet>(); ftpLets.put("ftpService", new MyFtpPlet()); serverFactory.setFtplets(ftpLets); // 6、读取用户的配置信息 // 注意:配置文件位于resources目录下,如果项目使用内置容器打成jar包发布,FTPServer无法直接直接读取Jar包中的配置文件。 // 解决办法:将文件复制到指定目录(本文指定到根目录)下然后FTPServer才能读取到。 /* PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory(); String tempPath = System.getProperty("java.io.tmpdir") + System.currentTimeMillis() + ".properties"; File tempConfig = new File(tempPath); ClassPathResource resource = new ClassPathResource("users.properties"); IOUtils.copy(resource.getInputStream(), new FileOutputStream(tempConfig)); userManagerFactory.setFile(tempConfig); userManagerFactory.setPasswordEncryptor(new ClearTextPasswordEncryptor()); //密码以明文的方式 serverFactory.setUserManager(userManagerFactory.createUserManager()); */ // 6.2、基于数据库来存储用户实例 DbUserManagerFactory dbUserManagerFactory = new DbUserManagerFactory(); // todo.... System.out.println("======================================"); System.out.println(this.yml.getAdminname()); dbUserManagerFactory.setDataSource(dataSource); dbUserManagerFactory.setAdminName(this.yml.getAdminname()); dbUserManagerFactory.setSqlUserAdmin(this.yml.getSqluseradmin()); dbUserManagerFactory.setSqlUserInsert(this.yml.getSqluserinsert()); dbUserManagerFactory.setSqlUserDelete(this.yml.getSqluserdelete()); dbUserManagerFactory.setSqlUserUpdate(this.yml.getSqluserupdate()); dbUserManagerFactory.setSqlUserSelect(this.yml.getSqluserselect()); dbUserManagerFactory.setSqlUserSelectAll(this.yml.getSqluserselectall()); dbUserManagerFactory.setSqlUserAuthenticate(this.yml.getSqluserauthenticate()); dbUserManagerFactory.setPasswordEncryptor(new ClearTextPasswordEncryptor()); //密码以明文的方式 serverFactory.setUserManager(dbUserManagerFactory.createUserManager()); // 7、实例化FTP Server server = serverFactory.createServer(); } /** * ftp server start */ public void start() { try { server.start(); logger.info("Apache Ftp server is starting!"); } catch (FtpException e) { e.printStackTrace(); } } /** * ftp server stop */ public void stop() { server.stop(); logger.info("Apache Ftp server is stoping!"); }}创建配置监听器Listener类package com.qingfeng.ftpserver.listener;import com.qingfeng.ftpserver.mysqldatasource.MyFtpServer;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.web.context.support.WebApplicationContextUtils;import javax.servlet.ServletContextEvent;import javax.servlet.ServletContextListener;import javax.servlet.annotation.WebListener;@WebListenerpublic class FtpServerListener implements ServletContextListener { private static final Logger logger = LoggerFactory.getLogger(MyFtpServer.class); private static final String SERVER_NAME="FTP-SERVER"; @Autowired private MyFtpServer server; //容器初始化调用 *** start ftpServer public void contextInitialized(ServletContextEvent sce) { WebApplicationContextUtils.getRequiredWebApplicationContext(sce.getServletContext()) .getAutowireCapableBeanFactory().autowireBean(this);//必须添加的代码 sce.getServletContext().setAttribute(SERVER_NAME,server); try { System.out.println("===================111==================="); System.out.println(server); //项目启动时已经加载好了 server.start(); System.out.println("Apache Ftp server is started!"); logger.info("Apache Ftp server is started!"); } catch (Exception e){ e.printStackTrace(); throw new RuntimeException("Apache Ftp server start failed!", e); } } //容器关闭时调用 *** stop ftpServer public void contextDestroyed(ServletContextEvent sce) { server.stop(); sce.getServletContext().removeAttribute(SERVER_NAME); logger.info("Apache Ftp server is stoped!"); System.out.println("Apache Ftp server is stoped!"); }}创建MyFtpPlet实现监听事件package com.qingfeng.ftpserver.ftplet;import org.apache.ftpserver.ftplet.*;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import java.io.File;import java.io.IOException;public class MyFtpPlet extends DefaultFtplet { private static final Logger logger = LoggerFactory.getLogger(MyFtpPlet.class); @Override public FtpletResult onLogin(FtpSession session, FtpRequest request) throws FtpException, IOException { // 获取上传文件的上传路径 String path = session.getUser().getHomeDirectory(); // 获取上传用户 String name = session.getUser().getName(); //校验文件夹路径是否存在 viladateDir(path); logger.info("用户:'{}'登录成功, 目录地址: '{}'", name, path); System.out.println("用户:'" + name + "'登录成功, 目录地址:'" + path + "'"); return super.onLogin(session, request); } @Override public FtpletResult onUploadStart(FtpSession session, FtpRequest request) throws FtpException, IOException { // 获取上传文件的上传路径 String path = session.getUser().getHomeDirectory(); //校验文件夹路径是否存在 viladateDir(path); // 获取上传用户 String name = session.getUser().getName(); // 获取上传文件名 String filename = request.getArgument(); logger.info("用户:'{}',上传文件到目录:'{}',文件名称为:'{},状态:开始上传~'", name, path, filename); System.out.println("用户:'" + name + "',上传文件到目录:'" + path + "',文件名称为:'" + filename + "',状态:开始上传~"); return super.onUploadStart(session, request); } @Override public FtpletResult onUploadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException { // 获取上传文件的上传路径 String path = session.getUser().getHomeDirectory(); // 获取上传用户 String name = session.getUser().getName(); // 获取上传文件名 String filename = request.getArgument(); logger.info("用户:'{}',上传文件到目录:'{}',文件名称为:'{},状态:成功!'", name, path, filename); System.out.println("用户:'" + name + "',上传文件到目录:'" + path + "',文件名称为:'" + filename + "',状态:成功!'"); return super.onUploadEnd(session, request); } @Override public FtpletResult onDownloadStart(FtpSession session, FtpRequest request) throws FtpException, IOException { // todo servies... return super.onDownloadStart(session, request); } @Override public FtpletResult onDownloadEnd(FtpSession session, FtpRequest request) throws FtpException, IOException { // todo servies... return super.onDownloadEnd(session, request); } //判断文件夹是否存在,不存在则创建文件夹 public void viladateDir(String path) { File file = new File(path); // 如果文件夹不存在则创建 if (!file.exists() && !file.isDirectory()){ System.out.println("文件夹不存在,创建新的文件夹"); file.mkdir(); } }}创建FtpConfig配置类package com.qingfeng.ftpserver.config;import org.springframework.context.annotation.Configuration;import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;@Configurationpublic class FtpConfig implements WebMvcConfigurer { @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { //可以通过os来判断 String os = System.getProperty("os.name"); //linux设置 //registry.addResourceHandler("/ftp/**").addResourceLocations("file:/home/pic/"); //windows设置 //第一个 *** 设置访问路径前缀,第二个 *** 设置资源路径,既可以指定项目classpath路径,也可以指定其它非项目路径 registry.addResourceHandler("/ftp/**").addResourceLocations("file:D:\\FtpFileHome"); registry.addResourceHandler("/static/**").addResourceLocations("classpath:/static/"); }}创建参数Properties类package com.qingfeng.ftpserver.config;import org.springframework.boot.context.properties.ConfigurationProperties;import org.springframework.stereotype.Component;@Component@ConfigurationProperties(prefix = "ftp")public class YmlProperties { private String homedirectory; private String ftpport; private String passiveports; private String maxlogins; private String adminname; private String sqluseradmin; private String sqluserinsert; private String sqluserdelete; private String sqluserupdate; private String sqluserselect; private String sqluserselectall; private String sqluserauthenticate; public String getHomedirectory() { return homedirectory; } public void setHomedirectory(String homedirectory) { this.homedirectory = homedirectory; } public String getFtpport() { return ftpport; } public void setFtpport(String ftpport) { this.ftpport = ftpport; } public String getPassiveports() { return passiveports; } public void setPassiveports(String passiveports) { this.passiveports = passiveports; } public String getMaxlogins() { return maxlogins; } public void setMaxlogins(String maxlogins) { this.maxlogins = maxlogins; } public String getAdminname() { return adminname; } public void setAdminname(String adminname) { this.adminname = adminname; } public String getSqluseradmin() { return sqluseradmin; } public void setSqluseradmin(String sqluseradmin) { this.sqluseradmin = sqluseradmin; } public String getSqluserinsert() { return sqluserinsert; } public void setSqluserinsert(String sqluserinsert) { this.sqluserinsert = sqluserinsert; } public String getSqluserdelete() { return sqluserdelete; } public void setSqluserdelete(String sqluserdelete) { this.sqluserdelete = sqluserdelete; } public String getSqluserupdate() { return sqluserupdate; } public void setSqluserupdate(String sqluserupdate) { this.sqluserupdate = sqluserupdate; } public String getSqluserselect() { return sqluserselect; } public void setSqluserselect(String sqluserselect) { this.sqluserselect = sqluserselect; } public String getSqluserselectall() { return sqluserselectall; } public void setSqluserselectall(String sqluserselectall) { this.sqluserselectall = sqluserselectall; } public String getSqluserauthenticate() { return sqluserauthenticate; } public void setSqluserauthenticate(String sqluserauthenticate) { this.sqluserauthenticate = sqluserauthenticate; }}配置application.ymlspring: datasource: driver-class-name: com.mysql.jdbc.Driver url: jdbc:mysql://localhost:3306/mina_ftp?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC username: root password: Root@123ftp: homedirectory: D:/FtpFileHome ftpport: 2121 passiveports: 10000-10500 maxlogins: 20 adminname: admin sqluseradmin: SELECT userid FROM FTP_USER WHERE userid='{userid}' AND userid='admin' sqluserinsert: INSERT INTO FTP_USER (userid, userpassword, homedirectory,enableflag, writepermission, idletime, uploadrate, downloadrate) VALUES ('{userid}', '{userpassword}', '{homedirectory}', {enableflag}, {writepermission}, {idletime}, uploadrate}, {downloadrate}) sqluserdelete: DELETE FROM FTP_USER WHERE userid = '{userid}' sqluserupdate: UPDATE FTP_USER SET userpassword='{userpassword}',homedirectory='{homedirectory}',enableflag={enableflag},writepermission={writepermission},idletime={idletime},uploadrate={uploadrate},downloadrate={downloadrate},maxloginnumber={maxloginnumber}, maxloginperip={maxloginperip} WHERE userid='{userid}' sqluserselect: SELECT userid,userpassword,CONCAT('${ftp.homedirectory}',homedirectory) as homedirectory,enableflag,writepermission,idletime,uploadrate,downloadrate,maxloginnumber,maxloginperip FROM ftp_user WHERE userid = '{userid}' sqluserselectall: SELECT userid FROM FTP_USER ORDER BY userid sqluserauthenticate: SELECT userid, userpassword FROM FTP_USER WHERE userid='{userid}'启动类配置@ServletComponentScan项目启动测试需要配置账号数据,参考如下:
使用Filezilla客户端测试:
海报
0 条评论
67
相关文章
本站已关闭游客评论,请登录或者注册后再评论吧~