添加ftp 服务 2023年3月11日15:59:44

master
zhangmeng 2023-03-11 15:59:54 +08:00
parent 387252e3d0
commit 7b0be2127a
6 changed files with 487 additions and 2 deletions

View File

@ -140,6 +140,10 @@
![](./src/main/resources/static/redame/img_29.png)
#### 8.2 ftp 服务工具
![](./src/main/resources/static/redame/img_31.png)
## 2. 开源项目总览
| 项目名称 |地址|

View File

@ -276,6 +276,12 @@
<artifactId>javax.mail</artifactId>
<version>1.6.2</version>
</dependency>
<dependency>
<groupId>org.apache.ftpserver</groupId>
<artifactId>ftpserver-core</artifactId>
<version>1.1.1</version>
</dependency>
</dependencies>
<build>

View File

@ -1,6 +1,30 @@
package com.zhangmeng.tools.controller;
import com.zhangmeng.tools.server.SimpleFtpServer;
import com.zhangmeng.tools.utils.AlertUtils;
import com.zhangmeng.tools.utils.ImagePath;
import javafx.beans.property.SimpleObjectProperty;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.scene.paint.Paint;
import javafx.scene.text.Text;
import javafx.stage.DirectoryChooser;
import javafx.stage.Stage;
import javafx.util.Callback;
import lombok.extern.slf4j.Slf4j;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author :
@ -10,5 +34,205 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j
public class FtpServerController {
public enum Status{
init("未启动"),
start("已启动"),
stop("已停止"),
;
private String desc;
Status(String desc) {
this.desc = desc;
}
public String getDesc() {
return desc;
}
public void setDesc(String desc) {
this.desc = desc;
}
}
@FXML
public Button server_start;
@FXML
public Button server_stop;
@FXML
public TextField user_name;
@FXML
public PasswordField password;
@FXML
public TextField resoureces_dir;
@FXML
public Text server_status;
@FXML
private Button add_user;
@FXML
private ListView<Data> server_list;
@FXML
private Button choose_file_dir;
private ObservableList<Data> list = FXCollections.observableArrayList();
private SimpleObjectProperty<Status> server_status_info = new SimpleObjectProperty<>();
private SimpleFtpServer simpleFtpServer = null;
@FXML
public void initialize() {
initStatus();
server_list.setPlaceholder(new Label("暂无服务信息!"));
server_list.setItems(list);
server_list.setCellFactory(new Callback<>() {
@Override
public ListCell<Data> call(ListView<Data> param) {
return new ListCell<>() {
@Override
protected void updateItem(Data data, boolean b) {
super.updateItem(data, b);
if (!b) {
HBox hBox = new HBox();
hBox.setAlignment(Pos.CENTER);
hBox.getChildren().add(new Label("username:" + data.username + ",password:" + data.password + ",rootDir:" + data.rootDir));
this.setGraphic(hBox);
}
}
};
}
});
server_list.setFixedCellSize(40);
add_user.setOnAction(event -> {
if (user_name.getText().length() == 0 ){
AlertUtils.alert_warning("用户名不能为空!");
return;
}
if (password.getText().length() == 0 ){
AlertUtils.alert_warning("密码不能为空!");
return;
}
if (resoureces_dir.getText().length() == 0 ){
AlertUtils.alert_warning("资源文件夹不能为空!");
return;
}
Data data = new Data();
data.setUsername(user_name.getText());
data.setPassword(password.getText());
data.setRootDir(resoureces_dir.getText());
list.add(data);
//清楚输入框
user_name.setText(null);
password.setText(null);
resoureces_dir.setText(null);
});
server_start.setOnAction(event -> {
simpleFtpServer = SimpleFtpServer.create();
for (Data item : server_list.getItems()) {
BaseUser user = new BaseUser();
List<Authority> list = new ArrayList<>();
list.add(new WritePermission());
user.setAuthorities(list);
user.setName(item.username);
user.setPassword(item.password);
user.setHomeDirectory(item.rootDir);
simpleFtpServer.addUser(user);
}
simpleFtpServer.start();
startStatus();
});
server_stop.setOnAction(event -> {
simpleFtpServer.stop();
stopStatus();
});
choose_file_dir.setText(null);
ImageView iv = new ImageView(new Image(ImagePath.path(ImagePath.ImagePathType.IMAGE_FILE)));
iv.setPreserveRatio(true);
iv.setFitWidth(18);
choose_file_dir.setGraphic(iv);
choose_file_dir.setOnAction(event -> {
Stage stage = new Stage();
DirectoryChooser dc = new DirectoryChooser();
dc.setTitle("文件夹选择器");
File file = dc.showDialog(stage);
if (file == null){
return;
}
resoureces_dir.setText(file.getPath());
});
}
private void stopStatus(){
server_status.setFill(Paint.valueOf("#ccffccff"));
server_status.setText(Status.stop.desc);
server_status_info.set(Status.stop);
}
private void startStatus(){
server_status.setFill(Paint.valueOf("#ccffccff"));
server_status.setText(Status.start.desc);
server_status_info.set(Status.start);
}
private void initStatus(){
server_status.setFill(Paint.valueOf("#ccffccff"));
server_status.setText(Status.init.desc);
server_status_info.set(Status.init);
}
public static class Data{
private String username;
private String password;
private String rootDir;
public Data() {
}
public Data(String username, String password, String rootDir) {
this.username = username;
this.password = password;
this.rootDir = rootDir;
}
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 getRootDir() {
return rootDir;
}
public void setRootDir(String rootDir) {
this.rootDir = rootDir;
}
}
}

View File

@ -0,0 +1,229 @@
package com.zhangmeng.tools.server;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.net.NetUtil;
import cn.hutool.extra.ftp.FtpException;
import org.apache.ftpserver.ConnectionConfig;
import org.apache.ftpserver.FtpServer;
import org.apache.ftpserver.FtpServerFactory;
import org.apache.ftpserver.ftplet.Authority;
import org.apache.ftpserver.ftplet.Ftplet;
import org.apache.ftpserver.ftplet.User;
import org.apache.ftpserver.ftplet.UserManager;
import org.apache.ftpserver.listener.ListenerFactory;
import org.apache.ftpserver.ssl.SslConfiguration;
import org.apache.ftpserver.ssl.SslConfigurationFactory;
import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory;
import org.apache.ftpserver.usermanager.impl.BaseUser;
import org.apache.ftpserver.usermanager.impl.WritePermission;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author :
* @version : 1.0
* @date : 2023-03-11 15:05
*/
public class SimpleFtpServer {
/**
* FTP{@link SimpleFtpServer#start()}
*
* @return SimpleFtpServer
*/
public static SimpleFtpServer create() {
return new SimpleFtpServer();
}
FtpServerFactory serverFactory;
ListenerFactory listenerFactory;
FtpServer ftpServer;
/**
*
*/
public SimpleFtpServer() {
serverFactory = new FtpServerFactory();
listenerFactory = new ListenerFactory();
}
/**
* {@link FtpServerFactory}FTP
*
* @return {@link FtpServerFactory}
*/
public FtpServerFactory getServerFactory() {
return this.serverFactory;
}
/**
* 使ConnectionConfigFactory{@link ConnectionConfig}
*
* @param connectionConfig
* @return this
*/
public SimpleFtpServer setConnectionConfig(ConnectionConfig connectionConfig) {
this.serverFactory.setConnectionConfig(connectionConfig);
return this;
}
/**
* {@link ListenerFactory}SSL
*
* @return {@link ListenerFactory}
*/
public ListenerFactory getListenerFactory() {
return this.listenerFactory;
}
/**
* 使21
*
* @param port
* @return this
*/
public SimpleFtpServer setPort(int port) {
Assert.isTrue(NetUtil.isValidPort(port), "Invalid port!");
this.listenerFactory.setPort(port);
return this;
}
/**
*
*
* @return
*/
public UserManager getUserManager() {
return this.serverFactory.getUserManager();
}
/**
* FTP
*
* @param user FTP
* @return this
*/
public SimpleFtpServer addUser(User user) {
try {
getUserManager().save(user);
} catch (org.apache.ftpserver.ftplet.FtpException e) {
throw new FtpException(e);
}
return this;
}
/**
*
*
* @param homePath
* @return this
*/
public SimpleFtpServer addAnonymous(String homePath) {
BaseUser user = new BaseUser();
user.setName("anonymous");
user.setHomeDirectory(homePath);
List<Authority> authorities = new ArrayList<>();
// 添加用户读写权限
authorities.add(new WritePermission());
user.setAuthorities(authorities);
return addUser(user);
}
/**
*
*
* @param userName
* @return this
*/
public SimpleFtpServer delUser(String userName) {
try {
getUserManager().delete(userName);
} catch (org.apache.ftpserver.ftplet.FtpException e) {
throw new FtpException(e);
}
return this;
}
/**
* 使SSL使SslConfigurationFactory{@link SslConfiguration}
*
* @param ssl {@link SslConfiguration}
* @return this
*/
public SimpleFtpServer setSsl(SslConfiguration ssl) {
this.listenerFactory.setSslConfiguration(ssl);
listenerFactory.setImplicitSsl(true);
return this;
}
/**
* 使SSL
*
* @param keystoreFile
* @param password
* @return this
*/
public SimpleFtpServer setSsl(File keystoreFile, String password) {
SslConfigurationFactory sslFactory = new SslConfigurationFactory();
sslFactory.setKeystoreFile(keystoreFile);
sslFactory.setKeystorePassword(password);
return setSsl(sslFactory.createSslConfiguration());
}
/**
* 使
*
* @param userManager {@link UserManager}
* @return this
*/
public SimpleFtpServer setUserManager(UserManager userManager) {
this.serverFactory.setUserManager(userManager);
return this;
}
/**
*
*
* @param propertiesFile
* @return this
*/
public SimpleFtpServer setUsersConfig(File propertiesFile) {
final PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory();
userManagerFactory.setFile(propertiesFile);
return this.setUserManager(userManagerFactory.createUserManager());
}
/**
* FTP{@link Ftplet}
*
* @param name
* @param ftplet {@link Ftplet}
* @return this
*/
public SimpleFtpServer addFtplet(String name, Ftplet ftplet) {
this.serverFactory.getFtplets().put(name, ftplet);
return this;
}
/**
* FTP线
*/
public void start() {
// 一个Listener对应一个监听端口
// 可以创建多个监听,此处默认只监听一个
serverFactory.addListener("default", listenerFactory.createListener());
try {
ftpServer = serverFactory.createServer();
ftpServer.start();
} catch (org.apache.ftpserver.ftplet.FtpException e) {
throw new FtpException(e);
}
}
public void stop() {
ftpServer.stop();
}
}

View File

@ -1,6 +1,28 @@
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.text.Text?>
<AnchorPane fx:controller="com.zhangmeng.tools.controller.FtpServerController" prefHeight="649.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" />
<AnchorPane prefHeight="649.0" prefWidth="1200.0" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="com.zhangmeng.tools.controller.FtpServerController">
<children>
<Label layoutX="78.0" layoutY="98.0" text="用户名:" />
<Label layoutX="84.0" layoutY="154.0" text="密码:" />
<Button fx:id="server_start" layoutX="443.0" layoutY="400.0" mnemonicParsing="false" text="启动ftp服务" AnchorPane.bottomAnchor="224.0" />
<Button fx:id="server_stop" layoutX="614.0" layoutY="400.0" mnemonicParsing="false" text="停止服务" AnchorPane.bottomAnchor="224.0" />
<TextField fx:id="user_name" layoutX="131.0" layoutY="94.0" prefHeight="25.0" prefWidth="331.0" />
<PasswordField fx:id="password" layoutX="131.0" layoutY="150.0" prefHeight="25.0" prefWidth="331.0" />
<ListView fx:id="server_list" layoutX="629.0" layoutY="94.0" prefHeight="224.0" prefWidth="501.0" AnchorPane.bottomAnchor="331.0" AnchorPane.leftAnchor="629.0" AnchorPane.rightAnchor="70.0" AnchorPane.topAnchor="94.0" />
<Label layoutX="563.0" layoutY="98.0" text="服务列表:" />
<Label layoutX="59.0" layoutY="212.0" text="资源目录:" />
<TextField fx:id="resoureces_dir" layoutX="131.0" layoutY="208.0" prefHeight="25.0" prefWidth="331.0" />
<Button fx:id="add_user" layoutX="258.0" layoutY="287.0" mnemonicParsing="false" text="添加" />
<Label layoutX="82.0" layoutY="404.0" text="服务状态:" AnchorPane.bottomAnchor="228.0" />
<Text fx:id="server_status" layoutX="155.0" layoutY="417.0" strokeType="OUTSIDE" strokeWidth="0.0" text="服务状态" AnchorPane.bottomAnchor="228.0" />
<Button fx:id="choose_file_dir" layoutX="477.0" layoutY="208.0" mnemonicParsing="false" text="选择文件夹" />
</children>
</AnchorPane>

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB