最近跟外部业务系统进行数据对接,其中涉及到对方要获取我们到附件,跟同事商量了一下后,最后决定搭建一个 ftp 文件服务器,让对方通过 url 从 ftp 服务器下载附件。之前没搭建过ftp服务器,了解了一下之后,发现大多是使用 vsftpd 软件去实现,才发现平时从各种电影网站下载电影到时候,那些 ftp:// 开头的下载链接都是 ftp 文件服务器,原来都不需要写代码。。。
安装vsftpd
运行 yum -y install vsftpd
命令进行安装,安装完成之后可以查看安装的版本如下:
可以看到配置文件也都在etc目录下
在vsftpd的相关路径中可以看到 /usr/lib/systemd/system/vsftpd.service
文件,所以也可以使用 systemctl
来管理 vsftpd 的服务。
vsftpd配置
vsftpd 默认开启匿名登陆,在启动服务之后,ftp文件夹默认在 /var/ftp/pub
, 在浏览器中输入 ftp://172.16.133.133/
即可以看 pub 文件夹,如果目录下有文件都话,点击文件即可以下载。
vsftpd 有三种登陆方式
- 匿名登陆
- 新建linux系统级别用户,再配置成 vsftpd 用户,通过用户名和密码登陆
- 配置 vsftpd 虚拟用户,通过配置的用户名和密码登陆
本次选择配置虚拟用户的方式控制用户登陆,个人感觉这样会比较好。
编辑 /etc/vsftpd/vsftpd.conf
配置文件
-
禁用匿名登陆
1 2 3 4 5 6 7 8 9 10 11 12 13
# 不允许匿名用户登入。 anonymous_enable=NO # 是否允许本地用户登入,YES时可以通过linux系统用户登陆,文件目录默认为/home下的对应用户目录。 local_enable=YES # 是否允许登陆用户有写权限。属于全局设置,默认值为YES。 write_enable=YES/NO(YES) # 用于指定用户列表文件中的用户不允许切换到上级目录。 chroot_local_user=YES # 还有很多其他配置项,可以根据情况自己设定。
此时重启服务,刷新浏览器,会发现弹出登陆框,输入linux系统用户即可登陆到该用户目录下。
-
配置虚拟用户登陆
1 2 3 4 5 6 7 8 9 10 11
# 增加,启用虚拟用户模式 guest_enable=YES # 增加,配置虚拟用户映射到的本地用户名 guest_username=wtg # 修改,配置虚拟用户的认证方式 pam_service_name=/etc/pam.d/ftpvuser.pam # 增加,虚拟用户的配置文件目录 user_config_dir=/etc/vsftpd/vuser.d
-
刚刚配置了虚拟用户到认证方式,现在我们创建相关文件
创建授权认证文件,进入
/etc/pam.d/
目录,备份原来的 vsftpd 文件,创建新的 vsftpd 文件,内容如下:1 2 3
#%PAM-1.0 auth required pam_userdb.so db=/etc/vsftpd/vuser.d/vuser account required pam_userdb.so db=/etc/vsftpd/vuser.d/vuser
创建虚拟用户的秘钥文件,此文件的格式为第一行是用户名,第二行是密码,第三行是用户名,第四行是密码,以此类推可以添加多个,执行
vi /etc/vsftpd/vuser.d/vuser.list
,添加如下内容:1 2
vwtg vwtg
使用db_load工具生成加密
vuser.list
此处尴尬的是本地虚拟机无法操作,因为我虚拟机装的CentOs7,竟然找不到db4的包,下载离线的rpm包也找不到,db4还停留在CentOs6,无法继续操作下去。网上的博客大多写的没有顺序或不够明确,本来想实际操作然后按顺序记录的,现在有点不太确定是否配置正确和完整了,不过思路是没有问题的,同事在公司的CentOs6上安装了一个,可以使用
1 2 3 4 5 6 7 8
# 安装db4工具 yum install db4-utils -y # 加密 db_load -T -t hash -f vuser.list vuser.db file vuser.list file vuser.db
每个用户单独配置文件
/etc/vsftpd/vuser.d/vwtg
,文件名为虚拟用户名,可以根据需要添加相关配置内容:1 2 3 4 5 6 7 8
# 写权限 write_enable=NO # 宿主目录 local_root=/home/wtg # 能否上传 anon_upload_enable=NO
配置完成重启服务器,如果一切正常,就可以使用虚拟用户登陆ftp服务器了。
java利用ftp协议上传下载文件到ftp服务器
-
引入相关依赖
1 2 3 4 5
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.6</version> </dependency>
-
上传代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71
/** * @author : wangtiegang * @date : Create in 2019/7/1 10:14 */ public class FtpUtils { private static final Logger log = LoggerFactory.getLogger(FtpUtils.class); /** * 通过ftp服务上传文件 * @param host * @param port * @param username * @param password * @param filename * @param input * @return */ public static boolean uploadFile(String host, int port, String username, String password, String targetPath, String filename, InputStream input) { boolean result = false; FTPClient ftp = new FTPClient(); try { int reply; // 连接FTP服务器 ftp.connect(host, port); // 登录 ftp.login(username, password); reply = ftp.getReplyCode(); if (!FTPReply.isPositiveCompletion(reply)) { log.error("FTP服务器返回状态码不合法: " + reply); ftp.disconnect(); return result; } //切换到上传目录 if (!ftp.changeWorkingDirectory(targetPath)) { // 如果目录不存在创建目录 if(ftp.makeDirectory(targetPath)){ ftp.changeWorkingDirectory(targetPath); }else { log.error("ftp服务器创建目标路径失败:" + targetPath); return result; } } // 客户端开启被动模式,不开启被动模式会导致上传文件内容为空的情况 ftp.enterLocalPassiveMode(); // 设置上传文件的类型为二进制类型 ftp.setFileType(FTP.BINARY_FILE_TYPE); // 上传文件, ftp服务默认ISO-8859-1编码 String isoName = new String(filename.getBytes("UTF-8"),"ISO-8859-1"); if (!ftp.storeFile(isoName, input)) { log.error("ftp服务器保存文件失败:" + filename); return result; } input.close(); ftp.logout(); result = true; } catch (IOException e) { log.error("ftp服务器上传文件失败:" + filename, e); } finally { if (ftp.isConnected()) { try { ftp.disconnect(); } catch (IOException ioe) { log.error("ftp服务器断开连接失败:" + filename, ioe); } } } return result; } }
-
下载代码跟上传代码差不多,由于是业务系统那边技术写的,此处就不展示了。