• vsftp文件服务器的搭建与使用案例


    一、Linux 云服务器搭建 FTP 服务

    1.执行以下命令,安装 vsftpd。

    yum install -y vsftpd

    2.执行以下命令,设置 vsftpd 开机自启动。

    systemctl enable vsftpd

    3.执行以下命令,启动 FTP 服务

    systemctl start vsftpd

    4.执行以下命令,确认服务是否启动

    netstat -antup | grep ftp

    5.配置 vsftpd

    5.1.执行以下命令,为 FTP 服务创建一个 Linux 用户,本文以 ftpuser 为例。

    useradd ftpuser

    5.2.执行以下命令,设置 ftpuser 用户的密码

    passwd ftpuser

    5.3.执行以下命令,创建 FTP 服务使用的文件目录,本文以 /var/ftp/test 为例。

    mkdir /var/ftp/test

    5.4.执行以下命令,修改目录权限

    chown -R ftpuser:ftpuser /var/ftp/test

    5.6.执行以下命令,打开 vsftpd.conf 文件

    vim /etc/vsftpd/vsftpd.conf

    5.7.修改以下配置参数

    主动模式配置:

    1. anonymous_enable=NO
    2. local_enable=YES
    3. write_enable=YES
    4. chroot_local_user=YES
    5. chroot_list_enable=YES
    6. chroot_list_file=/etc/vsftpd/chroot_list
    7. listen=YES
    8. #listen_ipv6=YES

    被动模式配置:

    1. local_root=/var/ftp/test
    2. allow_writeable_chroot=YES
    3. pasv_enable=YES
    4. pasv_address=xxx.xx.xxx.xx #请修改为您的 Linux 云服务器公网 IP
    5. pasv_min_port=40000
    6. pasv_max_port=45000

     按Esc 后输入 :wq 保存后退出.

    5.8.执行以下命令,重启 FTP 服务。

    systemctl restart vsftpd

    安装教程参考如下地址:云服务器 Linux 云服务器搭建 FTP 服务-最佳实践-文档中心-腾讯云

    FTP客户端下载:FileZilla中文网 - 免费开源的FTP解决方案

    二、使用教程

    建立连接:

    1. //需要连接到的ftp端的ip
    2. @Value(value = "${ftp.ip}")
    3. private String ip;
    4. //连接端口,默认21
    5. @Value(value = "${ftp.prot}")
    6. private int port;
    7. //要连接到的ftp端的名字
    8. @Value(value = "${ftp.username}")
    9. private String name;
    10. //要连接到的ftp端的对应得密码
    11. @Value(value = "${ftp.password}")
    12. private String pwd;
    13. @Value(value = "${ftp.ftpUrl}")
    14. private String ftpUrl;
    15. //ftp对象
    16. private FTPClient ftp;
    17. /**
    18. * 1.连接ftp
    19. * 调用此方法,输入对应得ip,端口,要连接到的ftp端的名字,要连接到的ftp端的对应得密码。连接到ftp对象,并验证登录进入fto
    20. */
    21. public boolean ftp1() {
    22. ftp = new FTPClient();
    23. try {
    24. if (!ftp.isConnected()) {
    25. ftp.connect(ip, port);
    26. }
    27. log.info("连接状态:" + ftp.login(name, pwd));
    28. ftp.setCharset(Charset.forName("UTF-8"));
    29. ftp.setControlEncoding("UTF-8");
    30. // ftp.enterLocalActiveMode(); //主动模式
    31. ftp.enterLocalPassiveMode(); // 被动模式
    32. return true;
    33. } catch (IOException e) {
    34. e.printStackTrace();
    35. }
    36. return false;
    37. }
    38. public CommonResultVo threeDAndEightDReports() {
    39. //抱怨单号、FTP地址、3D/8D文件类型
    40. log.info("-------------ftpUrl地址:" + ip);
    41. boolean flag = this.ftp1(); //1.连接FTP
    42. if (flag) {
    43. try {
    44. this.gmRead(ftpUrl); //2.获取文件、解析文件内容,进库操作
    45. this.disconnect(); //3. 关闭连接
    46. return CommonResultVo.failed("FTP数据发送MQ完成");
    47. } catch (Exception e) {
    48. e.printStackTrace();
    49. }
    50. }
    51. return CommonResultVo.failed("连接FTP失败");
    52. }
    53. /**
    54. * 2.获取文件、解析文件内容,进库操作
    55. */
    56. public void gmRead(String ftpUrl) throws IOException {
    57. boolean downloadResult = false;
    58. try {
    59. ftp.changeWorkingDirectory(ftpUrl);
    60. log.info("远程路径为*************************" + ftpUrl);
    61. FTPFile[] files = ftp.listFiles(ftpUrl); // 通过路径得到文件
    62. log.info("文件数量为*************************" + files.length);
    63. for (int i = 0; i < files.length; i++) {
    64. FTPFile file = files[i];
    65. if (file.isFile()) {
    66. // downloadResult = this.download(file);// 下载文件 到本地读取路径
    67. // this.downloadFtpFile(file);
    68. new FTPDownload().downloadToFileAll(ftp, ftpUrl);
    69. } else {
    70. log.info("************* 文件不存在 ************");
    71. }
    72. }
    73. } catch (Exception e) {
    74. e.printStackTrace();
    75. }
    76. }

    文件下载:

    1. import static com.cetc.service.impl.MessageServicesImpl.pathStr;
    2. /**
    3. * @author :jerry
    4. * @date :Created in 2022/10/25 11:04
    5. * @description:FTP文件下载
    6. * @version: V1.1
    7. */
    8. @Slf4j
    9. public class FTPDownload {
    10. //下载存放路径
    11. public static final String pathStr = Paths.get("upload").toAbsolutePath().toString();
    12. private FTPClient ftp;
    13. /**
    14. * 1.普通下载
    15. */
    16. public synchronized void downloadToFile(FTPClient ftp, String pathname, String filename) throws IOException {
    17. //删除文件
    18. File directory = new File(pathStr);
    19. Files.walk(directory.toPath()).filter(Files::isRegularFile).map(Path::toFile).forEach(File::delete);
    20. log.info("删除"+pathStr+"目录下的所有历史文件成功");
    21. try {
    22. this.ftp = ftp;
    23. //切换FTP目录
    24. ftp.setFileType(FTP.BINARY_FILE_TYPE);
    25. ftp.changeWorkingDirectory(pathname);
    26. FTPFile[] ftpFiles = ftp.listFiles();
    27. for (FTPFile file : ftpFiles) {
    28. if (filename.equalsIgnoreCase(file.getName())) {
    29. File localFile = new File(pathStr + "/" + filename);
    30. OutputStream is = new FileOutputStream(localFile);
    31. ftp.retrieveFile(file.getName(), is);
    32. is.close();
    33. break;
    34. }
    35. }
    36. ftp.logout();
    37. log.info("下载文件成功");
    38. } catch (Exception e) {
    39. log.error("下载文件失败");
    40. e.printStackTrace();
    41. } finally {
    42. if (ftp.isConnected()) {
    43. try {
    44. ftp.disconnect();
    45. } catch (IOException e) {
    46. e.printStackTrace();
    47. }
    48. }
    49. }
    50. }
    51. /**
    52. * 2.字节流的形式下载文件
    53. */
    54. public ByteArrayOutputStream byteDownloadZip(FTPClient ftp, FTPFile filePath) {
    55. this.ftp = ftp;
    56. ByteArrayOutputStream bos = null;
    57. try {
    58. //切换FTP目录
    59. ftp.setFileType(FTP.BINARY_FILE_TYPE);
    60. ftp.changeWorkingDirectory(pathStr);
    61. FTPFile[] ftpFiles = ftp.listFiles();
    62. String filename = filePath.getName();
    63. for (FTPFile file : ftpFiles) {
    64. if (filename.equalsIgnoreCase(file.getName())) {
    65. InputStream is = ftp.retrieveFileStream(filename);
    66. bos = new ByteArrayOutputStream();
    67. int len = 0;
    68. byte[] buffer = new byte[1024];
    69. while ((len = is.read(buffer)) > 0) {
    70. bos.write(buffer, 0, len);
    71. }
    72. bos.flush();
    73. bos.close();
    74. is.close();
    75. ftp.completePendingCommand();
    76. break;
    77. }
    78. }
    79. ftp.logout();
    80. log.info("下载文件成功");
    81. } catch (Exception e) {
    82. log.error("下载文件失败");
    83. e.printStackTrace();
    84. } finally {
    85. if (ftp.isConnected()) {
    86. try {
    87. ftp.disconnect();
    88. } catch (IOException e) {
    89. e.printStackTrace();
    90. }
    91. }
    92. }
    93. System.out.println(bos);
    94. return bos;
    95. }
    96. /**
    97. * 下载全部FTP文件目录文件
    98. * */
    99. public synchronized void downloadToFileAll(FTPClient ftp, String pathname) {
    100. try {
    101. this.ftp = ftp;
    102. //切换FTP目录
    103. ftp.setFileType(FTP.BINARY_FILE_TYPE);
    104. ftp.changeWorkingDirectory(pathname);
    105. FTPFile[] ftpFiles = ftp.listFiles();
    106. for (FTPFile file : ftpFiles) {
    107. String filename = file.getName();
    108. log.info("filename:"+filename);
    109. File localFile = new File(pathStr + "/" + filename);
    110. OutputStream is = new FileOutputStream(localFile);
    111. ftp.retrieveFile(file.getName(), is);
    112. is.close();
    113. }
    114. ftp.logout();
    115. log.info("下载文件成功");
    116. } catch (Exception e) {
    117. log.error("下载文件失败");
    118. e.printStackTrace();
    119. } finally {
    120. if (ftp.isConnected()) {
    121. try {
    122. ftp.disconnect();
    123. } catch (IOException e) {
    124. e.printStackTrace();
    125. }
    126. }
    127. }
    128. }
    129. }
    1. import lombok.Builder;
    2. import lombok.Getter;
    3. import lombok.Setter;
    4. @Getter
    5. @Setter
    6. @Builder
    7. public class CommonResultVo {
    8. private int code;
    9. private String message;
    10. private T data;
    11. protected CommonResultVo() {
    12. }
    13. protected CommonResultVo(int code, String message, T data) {
    14. this.code = code;
    15. this.message = message;
    16. this.data = data;
    17. }
    18. /**
    19. * 成功返回结果
    20. *
    21. */
    22. public static CommonResultVo success() {
    23. return new CommonResultVo(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), null);
    24. }
    25. /**
    26. * 成功返回结果
    27. *
    28. * @param data 获取的数据
    29. */
    30. public static CommonResultVo success(T data) {
    31. return new CommonResultVo(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data);
    32. }
    33. /**
    34. * 成功返回结果
    35. *
    36. * @param data 获取的数据
    37. * @param message 提示信息
    38. */
    39. public static CommonResultVo success(T data, String message) {
    40. return new CommonResultVo(ResultCode.SUCCESS.getCode(), message, data);
    41. }
    42. /**
    43. * 失败返回结果
    44. * @param resultCode 错误码
    45. */
    46. public static CommonResultVo failed(ResultCode resultCode) {
    47. return new CommonResultVo(resultCode.getCode(), resultCode.getMessage(), null);
    48. }
    49. /**
    50. * 失败返回结果
    51. * @param resultCode 错误码
    52. * @param message 错误信息
    53. */
    54. public static CommonResultVo failed(ResultCode resultCode, String message) {
    55. return new CommonResultVo(resultCode.getCode(), message, null);
    56. }
    57. /**
    58. * 失败返回结果
    59. * @param message 提示信息
    60. */
    61. public static CommonResultVo failed(String message) {
    62. return new CommonResultVo(ResultCode.FAILED.getCode(), message, null);
    63. }
    64. /**
    65. * 失败返回结果
    66. */
    67. public static CommonResultVo failed() {
    68. return failed(ResultCode.FAILED);
    69. }
    70. }

     

    1. import lombok.Getter;
    2. import lombok.Setter;
    3. public enum ResultCode {
    4. SUCCESS(0, "操作成功"),
    5. FAILED(-1, "操作失败"),
    6. VALIDATE_FAILED(404, "参数检验失败"),
    7. UNAUTHORIZED(401, "暂未登录或token已经过期"),
    8. FORBIDDEN(403, "没有相关权限");
    9. @Setter
    10. @Getter
    11. private int code;
    12. @Setter
    13. @Getter
    14. private String message;
    15. private ResultCode(int code, String message) {
    16. this.code = code;
    17. this.message = message;
    18. }
    19. }

    yml配置如下:

    1. #个人测试
    2. ftp:
    3. ip: 10.10.10.121 #IP
    4. prot: 21 #端口
    5. ftpUrl: / #文件路径
    6. username: ftpuser #用户名
    7. password: 123456 #密码

     

    注意:

    ftp.changeWorkingDirectory(pathname);    //是切换到你的文件所在的目录,如果文件不在根目录,下载下来可能为0kb

  • 相关阅读:
    【一】【SQL】表的增删查改(部分)
    两道ospf 网络优化题目解析
    面试:gradle添加自定义task
    多维数组求和函数
    Konva事件机制
    重构从现在开始
    【Django】聚合查询——连接和聚合
    Leetcode2-AddTwoNumbers
    全志H616开发版
    物业系统自主研发接口测试框架
  • 原文地址:https://blog.csdn.net/qq_40068304/article/details/127846100