JAVA实现FTP文件上传下载及FTP服务器搭建

JAVA实现FTP文件上传下载及FTP服务器搭建



前言

最近项目中需要到FTP服务器中下载文件,于是花了点时间研究了一下,网上查了很多资料,都没有很详细的FTP服务器的搭建教程,踩了很多坑,终于搞定了,因此在此记录分享,如有错误,欢迎大家指正,谢谢!


一、FTP是什么?

FTP是一个专门进行文件管理的操作服务,一般来讲可以在任意的操作系统之中进行配置,但是如果考虑到简便性,一般来讲可以直接在Linux系统下进行安装。
FTP (File Transfer Protocol、文件传输协议)是TCP/IP协议中的一部分,属于应用层协议。使用FTP最主要的功能是对文件进行管理,所以在FTP内部对于文件支持有两种传输模式:文本模式(ASCII、默认)和二进制模式(Binary),通常文本文件使用ASCIl模式,而对于图片、视频、声音、压缩等文件则会使用二进制的方式进行传输。
FTP的操作一般是分为服务端以及客户端两个组成部分,客户端需要通过特定的FTP服务进行服务器的连接(大部分的FTP服务器上都是需要进行用户登录认证的)。

二、FTP两种模式

如果要进行FTP文件的管理,则客户端一定要与FTP服务器进行连接,在FTP中每一次通讯实际上都需要有两个连接存在,一个连接专门用于传输FTP命令、另外一个连接负责数据传送,所以在FTP中一般会支持两种不同的工作模式:一种是Standard模式(也被称为“PORT”模式),另外一种是Passive (也被称为“PASV”模式),这两种模式的概念如下:

  • PORT主动模式

当客户端与服务端连接后,客户端会打开一个新的本地端口,随后将此端口告诉给FTP服务端,这样FTP服务端就会主动的连接到FTP客户端公布的端口,随后进行数据传送。

  • PASV被动模式

FTP在定义的时候就公布了一个操作端口(一般为21端口),这样当客户端连接之后会明确的知道该操作端口并且进行数据传送。

在实际的FTP运行机制之中,如果要想通过FTP服务进行操作,则一般会使用被动模式,在所有的系统中几乎都会存在有防火墙的概念,如果要考虑到客户端的方便使用的话,被动的模式会更加的合理。

三、搭建FTP服务器

本文的FTP服务器是在CentOS7系统上搭建,FTP功能验证是在Windows10专业版。

安装FTP服务

[root@localhost ~]# yum install vsftpd

添加FTP访问用户

[root@localhost ~]# useradd myjftp

#设置密码,密码位数不足八位,会提示你无效的密码: 密码少于 8 个字符,不用管,继续设置即可。
[root@localhost ~]# passwd myjftp

创建用户能访问的目录且给于操作权限

[root@localhost ~]# mkdir -p /data/ftp_data
[root@localhost ~]# mkdir -p /data/ftp_data/anno

#为目录分配操作权限,注意,匿名用户一定不能有写权限
[root@localhost ~]# chmod o+w /data/ftp_data/

修改FTP服务配置文件

[root@localhost ~]# cd /etc/vsftpd/
[root@localhost vsftpd]# ll
总用量 20
-rw-------. 1 root root  125 610 2021 ftpusers
-rw-------. 1 root root  361 610 2021 user_list
-rw-------. 1 root root 5116 610 2021 vsftpd.conf
-rwxr--r--. 1 root root  338 610 2021 vsftpd_conf_migrate.sh

#备份配置文件,且删除文件中的注释内容
[root@localhost vsftpd]# mv vsftpd.conf vsftpd.conf.bak
[root@localhost vsftpd]# grep -v "#" vsftpd.conf.bak >vsftpd.conf
#修改配置文件
[root@localhost vsftpd]# vim vsftpd.conf

#配置内容如下,复制即可:
anonymous_enable=YES
local_enable=YES
write_enable=YES
local_umask=022

anon_root=/data/ftp_data/anon
anon_upload_enable=YES
anon_mkdir_write_enable=YES

local_root=/data/ftp_data
chroot_local_user=YES
#限制本地用户只能在根目录
allow_writeable_chroot=YES

dirmessage_enable=YES
xferlog_enable=YES
connect_from_port_20=YES
xferlog_std_format=YES
listen=NO
listen_ipv6=YES

pam_service_name=vsftpd
userlist_enable=YES
tcp_wrappers=YES

配置文件各种配置解释如下,有需要可查看。

anonymous_enable         设置为NO,表示不允许匿名访问。
local_enable             设置为YES,表示允许本地用户登录。
chroot_local_user        设置为YES,这样我们就能限制用户在自己的目录中。
local_root               设置为/home/cppuser,这将用户的根目录设置为/home/cppuser。
write_enable             设置为YES,允许用户上传文件。
dirmessage_enable        设置为YES,这样用户在访问目录时会看到消息。
user_config_dir          设置为/etc/vsftpd/user_conf,这样我们就能为每个用户创建单独的配置文件。
local_root               设置为/home/cppuser/%u,这将用户的根目录设置为他们的用户名目录。
chroot_local_user        设置为YES,这样我们就能限制用户在自己的目录中。
secure_chroot_dir        设置为/etc/vsftpd/securefiles,这将用于存储用户的公钥。
chroot_list_enable       设置为YES,且设置下面的chroot_list_file。
chroot_list_file         设置/etc/vsftpd/chroot_list,这将列出所有被限制在自己目录的用户。
local_root               设置为/home/%u/%u,,这将用户的根目录设置为他们的用户名目录下的用户名目录。            
chroot_local_user        设置为YES,这样我们就能限制用户在自己的目录中。
chroot_list_enable       设置为YES,且设置下面的chroot_list_file
chroot_list_file         设置为/etc/vsftpd/chroot_list,这将列出所有被限制在自己目录的用户。
userlist_enable          设置为YES,且设置下面的userlist_file
userlist_file            设置为/etc/vsftpd/userlist,这将列出所有被禁止登录的用户。
passwd_file              设置为/etc/vsftpd/passwd,这将存储用户的密码。
auth_system              设置为YES,且设置下列auth_local
auth_local               设置为NO,这将使用系统的密码文件进行认证。
allow_anonlogin          设置为NO,这将阻止匿名用户登录。
anonymous_root           设置为/home/cppuser,这将匿名用户的根目录设置为/home/cppuser
ftp_username             设置为ftp,这将用于 FTP 认证的 Unix 用户名。
local_root               设置为/home/cppuser/%u,这将用户的根目录设置为他们的用户名目录。

启动FTP服务

[root@localhost vsftpd]# systemctl start vsftpd

防火墙永久性地添加 FTP 服务

[root@localhost vsftpd]# sudo firewall-cmd --permanent --add-service=ftp
success

#重新加载防火墙配置,使更改生效
[root@localhost vsftpd]# firewall-cmd --reload
success

#验证 FTP 服务是否已添加到防火墙中
[root@localhost vsftpd]# firewall-cmd --list-all
public (active)
  target: default
  icmp-block-inversion: no
  interfaces: ens33
  sources: 
  services: dhcpv6-client ftp ssh  【表示成功添加】
  ports: 
  protocols: 
  masquerade: no
  forward-ports: 
  source-ports: 
  icmp-blocks: 
  rich rules: 

设置SELinux的状态,SELinux的状态有Enforcing(强制执行)、Permissive(宽容)或者Disabled(禁用)三种状态,需要将它的状态设置为非Enforcing(强制执行)状态就行。

#查看SELinux的状态
[root@localhost vsftpd]# getenforce
Enforcing

#临时设置SELinux的状态为Permissive(宽容)
[root@localhost vsftpd]# setenforce 0

#永久设置状态方法
vi /etc/selinux/config
#将下列配置修改成你需要的状态即可
SELINUX=permissive

到此,FTP服务器就简单搭建完毕了,下面开始测试结果。
在/data/ftp_data/ 目录下新建文件hello.txt

[root@localhost ftp_data]# touch hello.txt
[root@localhost ftp_data]# ls
anno  hello.txt

打开本地Windows10系统的磁盘,在文件路径处直接输入ftp://你的IP地址 然后回车,输入账密。
在这里插入图片描述
在这里插入图片描述
哈哈,到此,FTP服务器就算搭建成功了!

三、JAVA实现FTP文件上传下载工具类

引入依赖

          <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.9.0</version>
        </dependency>

FTP工具类

package com.example.springbootmytest.ftp;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;

/**
 * FTP服务器文件上传下载工具类
 */
@Slf4j
public class FTPUtil {

    private static final int CONNECT_TIME_OUT = 5000;
    private static final String ENCODING ="UTF-8";

     /**
       * FTP服务器连接工具方法
       * @param host FTP服务器IP
       * @param port FTP服务器端口
       * @param userName FTP服务器用户名称
       * @param password FTP服务器用户密码
       */
    public static FTPClient connectFTP(String host,Integer port,String userName,String password) throws IOException {

        FTPClient client = new FTPClient();
        //连接服务器
        client.connect(host, port);
        //登录服务器
        client.login(userName, password);
        //设置连接超时时间
        client.setConnectTimeout(CONNECT_TIME_OUT);
        //设置编码格式
        client.setControlEncoding(ENCODING);
        // 设置文件传输编码类型, 字节传输:BINARY_FILE_TYPE, 文本传输:ASCII_FILE_TYPE, 建议使用BINARY_FILE_TYPE进行文件传输
        client.setFileType(FTP.BINARY_FILE_TYPE);
        // 设置为被动模式: enterLocalPassiveMode()
        client.enterLocalPassiveMode();
        return client;
    }

    /**
     * 上传本地文件到FTP文件目录
     * FTP服务器连接工具方法
     * @param host FTP服务器IP
     * @param port FTP服务器端口
     * @param userName FTP服务器用户名称
     * @param password FTP服务器用户密码
     * @param localAbsoluteFile 本地文件的绝对路径
     * @param ftpPath    FTP服务器的绝对路径目录
     * @throws IOException
     */
    public static void UploadFTPFile(String host,Integer port,String userName,String password,String localAbsoluteFile,String ftpPath) throws IOException {

        //连接服务器
        FTPClient client = null;
        FileInputStream fileInputStream = null;
        try {
            client = connectFTP(host,port,userName,password);
            //进入目录
            boolean existStatus = client.changeWorkingDirectory(ftpPath);
            if (!existStatus) {
                client.makeDirectory(ftpPath);
            }

            File file = new File(localAbsoluteFile);
            fileInputStream = new FileInputStream(file);
            //设置编码格式,防止出现乱码
            String tempPath = ftpPath + File.separator + file.getName();
            String ftpFileName = new String(tempPath.getBytes(StandardCharsets.UTF_8), "ISO-8859-1");
            boolean pushStatus = client.storeFile(ftpFileName, fileInputStream);
            if (pushStatus) {
                log.info("文件上传成功!");
            } else {
                log.info("文件上传失败!");
            }
        } catch (Exception e) {
            log.error("文件上传失败,失败原因:{}",e);
        } finally {
            if (fileInputStream != null) {
                fileInputStream.close();
            }
            if (client != null) {
                client.logout();
                client.disconnect();
            }
        }

    }

    /**
     * 从FTP服务上下载文件到本地目录
     * @param host FTP服务器IP
     * @param port FTP服务器端口
     * @param userName FTP服务器用户名称
     * @param password FTP服务器用户密码
     * @param ftpAbsoluteFile ftp服务器的文件绝对路径
     * @param localPath  本地目录
     * @throws IOException
     */
    public static void downloadFTPFile(String host,Integer port,String userName,String password,String ftpAbsoluteFile,String localPath)throws IOException{

        FTPClient client=null;
        FileOutputStream fileOutputStream=null;
        try{
            client = connectFTP(host,port,userName,password);
            File file = new File(localPath);
            if(!file.exists()){
                file.mkdirs();
            }
            //获取远程服务器上的文件名称和目录
            String[] split = ftpAbsoluteFile.split("/");
            String localFileName=split[split.length-1];

            String ftpAbsolutePath=ftpAbsoluteFile.substring(0,ftpAbsoluteFile.length()-localFileName.length());
            //进入目录
            client.changeWorkingDirectory(ftpAbsolutePath);
            fileOutputStream = new FileOutputStream(file.getAbsolutePath()+File.separator+localFileName);
            boolean pullStatus = client.retrieveFile(localFileName, fileOutputStream);
            if(pullStatus){
                log.info("文件下载成功!");
            }else{
               log.info("文件下载失败!");
            }
        }catch (Exception e){
            log.info("文件下载失败,原因原因:{}" ,e);
            e.printStackTrace();
        }finally {
            if (fileOutputStream != null) {
                fileOutputStream.close();
            }
            if (client != null) {
                client.logout();
                client.disconnect();
            }
        }

    }

}

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要搭建JavaFTP服务器,您可以按照以下步骤进行操作: 1. 在pom.xml文件中添加FTP服务器的依赖和管理版本: ```xml <properties> <ftpserver.version>1.1.1</ftpserver.version> </properties> <dependencies> <dependency> <groupId>org.apache.ftpserver</groupId> <artifactId>ftpserver-core</artifactId> <scope>compile</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.apache.ftpserver</groupId> <artifactId>ftpserver-core</artifactId> <version>${ftpserver.version}</version> </dependency> </dependencies> </dependencyManagement> ``` 2. 编写Java代码来搭建FTP服务器。您可以使用Apache FtpServer来实现: ```java import org.apache.ftpserver.FtpServer; import org.apache.ftpserver.FtpServerFactory; import org.apache.ftpserver.listener.ListenerFactory; import org.apache.ftpserver.usermanager.PropertiesUserManagerFactory; public class FtpServerExample { public static void main(String[] args) throws Exception { FtpServerFactory serverFactory = new FtpServerFactory(); ListenerFactory listenerFactory = new ListenerFactory(); listenerFactory.setPort(21); // 设置FTP服务器的端口号 serverFactory.addListener("default", listenerFactory.createListener()); PropertiesUserManagerFactory userManagerFactory = new PropertiesUserManagerFactory(); userManagerFactory.setFile(new File("users.properties")); // 指定用户属性文件的路径 serverFactory.setUserManager(userManagerFactory.createUserManager()); FtpServer server = serverFactory.createServer(); server.start(); } } ``` 3. 创建一个`users.properties`文件,用于指定FTP服务器的用户和密码。例如: ``` user1=password1,admin user2=password2 ``` 4. 运行Java代码,启动FTP服务器
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值