导读


原本在腾讯云搭建了一台Nginx和FTP服务器,用来作为图片保存之地。

使用步骤


1、依赖

SpringBoot项目导入以下依赖。

  1. <dependency>
  2. <groupId>commons-net</groupId>
  3. <artifactId>commons-net</artifactId>
  4. <version>3.6</version>
  5. </dependency>

2、FTP连接工厂

该连接工厂使用createFtpConnection创建FTP连接,ftpConnectionClose关闭FTP连接。

  1. import lombok.Data;
  2. import org.apache.commons.net.ftp.FTPClient;
  3. import org.apache.commons.net.ftp.FTPReply;
  4. import org.slf4j.Logger;
  5. import org.slf4j.LoggerFactory;
  6. import java.io.IOException;
  7. /**
  8. * FTP连接工厂
  9. *
  10. * @author chaohen
  11. * @date 2019/8/23
  12. */
  13. @Data
  14. public class FtpConnectionFactory {
  15. private static Logger LOGGER = LoggerFactory.getLogger(FtpConnectionFactory.class);
  16. /**
  17. * FTP ip地址
  18. */
  19. private static String address = "000.000.000.000";
  20. /**
  21. * FTP 端口号
  22. */
  23. private static int port = 21;
  24. /**
  25. * FTP 设置字符集
  26. */
  27. private static String charset = "GBK";
  28. /**
  29. * FTP 用户名
  30. */
  31. private static String username = "uftp";
  32. /**
  33. * FTP 密码
  34. */
  35. private static String password = "upwd123456";
  36. /**
  37. * ftpClient
  38. */
  39. private static FTPClient ftpClient;
  40. /**
  41. * 新建FTP连接
  42. *
  43. * @return
  44. */
  45. synchronized public static FTPClient createFtpConnection() {
  46. if (ftpClient == null || !ftpClient.isConnected()) {
  47. try {
  48. ftpClient = new FTPClient();
  49. //连接IP 如果port【端口】存在的话
  50. ftpClient.connect(address, port);
  51. //设置编码类型
  52. ftpClient.setControlEncoding(charset);
  53. //每次数据连接之前,ftpClient告诉ftp server开通一个端口来传输数据
  54. ftpClient.enterLocalPassiveMode();
  55. //登录
  56. ftpClient.login(username, password);
  57. //连接尝试后,应检查回复代码以验证
  58. int reply = ftpClient.getReplyCode();
  59. //没验证成功
  60. if (!FTPReply.isPositiveCompletion(reply)) {
  61. //断开ftp连接
  62. ftpClient.disconnect();
  63. return null;
  64. }
  65. LOGGER.info("The ftp server is successfully connected.");
  66. } catch (Exception e) {
  67. LOGGER.error("Failed to log in. The error message is: " + e.getMessage());
  68. }
  69. }
  70. return ftpClient;
  71. }
  72. /**
  73. * 关闭FTP连接 ftpClose
  74. */
  75. public static void ftpConnectionClose(FTPClient ftpClient) {
  76. if (ftpClient != null) {
  77. if (ftpClient.isConnected()) {
  78. try {
  79. ftpClient.disconnect();
  80. LOGGER.info("Ftp connection closed...");
  81. } catch (IOException e) {
  82. LOGGER.error("Ftp connection failed to disconnect, error message is:" + e.getMessage());
  83. }
  84. }
  85. }
  86. }
  87. }

3、FTP上传下载工具类

里面有两个方法,uploadFile用来上传,getFileByFtp用来下载。

  1. import com.heioky.filesystemupload.config.FtpConnectionFactory;
  2. import org.apache.commons.net.ftp.FTPClient;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import java.io.*;
  6. /**
  7. * ftp文件上传工具类
  8. *
  9. * @author hanyc
  10. * @date 2019/8/23
  11. */
  12. public class FtpFileUploadUtils {
  13. private static Logger logger = LoggerFactory.getLogger(FtpFileUploadUtils.class);
  14. /**
  15. * 文件上传
  16. *
  17. * @param remotePath 上传到远程的文件夹路径
  18. * @param originFileName 文件名
  19. * @param inputStream 文件流
  20. * @return
  21. */
  22. public static boolean uploadFile(String remotePath, String originFileName, InputStream inputStream) {
  23. //连接FTP
  24. FTPClient ftpClient = FtpConnectionFactory.createFtpConnection();
  25. try {
  26. // 设置文件类型(二进制)
  27. ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
  28. //创建文件夹,如果有的话 就不会创建,返回false
  29. ftpClient.makeDirectory(remotePath);
  30. // 设置上传目录
  31. ftpClient.changeWorkingDirectory(remotePath);
  32. //文件转移时候的一次性读取大小
  33. ftpClient.setBufferSize(1024);
  34. //将流写到服务器
  35. ftpClient.storeFile(originFileName, inputStream);
  36. inputStream.close();
  37. //ftp服务退出
  38. ftpClient.logout();
  39. return true;
  40. } catch (IOException e) {
  41. e.printStackTrace();
  42. } finally {
  43. if (ftpClient != null) {
  44. FtpConnectionFactory.ftpConnectionClose(ftpClient);
  45. }
  46. }
  47. return false;
  48. }
  49. /**
  50. * 下载文件
  51. *
  52. * @param remotePath ftp上文件存放的地址 如: /img/logo.png
  53. * @param localPath:本地存放文件的地址 如:E:\images\logo.png
  54. */
  55. public static void getFileByFtp(String remotePath, String localPath) {
  56. File localFile = new File(localPath);
  57. OutputStream ous = null;
  58. FTPClient ftpClient = FtpConnectionFactory.createFtpConnection();
  59. try {
  60. ous = new FileOutputStream(localFile);
  61. ftpClient.retrieveFile(remotePath, ous);
  62. } catch (FileNotFoundException e) {
  63. e.printStackTrace();
  64. logger.info("file not fount...");
  65. } catch (IOException e) {
  66. e.printStackTrace();
  67. } finally {
  68. if (ftpClient != null) {
  69. FtpConnectionFactory.ftpConnectionClose(ftpClient);
  70. }
  71. }
  72. }
  73. }

4、测试

4.1 controller层代码

  1. package com.heioky.filesystemupload.controller;
  2. import com.heioky.filesystemupload.utils.FtpFileUploadUtils;
  3. import org.slf4j.Logger;
  4. import org.slf4j.LoggerFactory;
  5. import org.springframework.stereotype.Controller;
  6. import org.springframework.web.bind.annotation.PostMapping;
  7. import org.springframework.web.bind.annotation.RequestMapping;
  8. import org.springframework.web.bind.annotation.ResponseBody;
  9. import org.springframework.web.multipart.MultipartFile;
  10. import java.io.*;
  11. import java.util.UUID;
  12. /**
  13. * 文件上传
  14. *
  15. * @author chaohen
  16. * @date 2019/8/22
  17. */
  18. @Controller
  19. @RequestMapping("/api")
  20. public class IndexController {
  21. private static final Logger logger = LoggerFactory.getLogger(IndexController.class);
  22. @PostMapping("/uploadFile")
  23. @ResponseBody
  24. public String updateAvatar(MultipartFile file) {
  25. try {
  26. if (!file.isEmpty()) {
  27. //获取文件(图片或者文件)的后缀名
  28. String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
  29. //拼接图片或文件名称,32位随机uuid+后缀名,当然也可以使用其他方式生成
  30. String fileName = UUID.randomUUID().toString().replace("-", "").toLowerCase() + suffix;
  31. InputStream inputStream = file.getInputStream();
  32. //调用ftp上传文件工具类,返回true成功,返回false失败
  33. Boolean flag = FtpFileUploadUtils.uploadFile("/", fileName, inputStream);
  34. if (flag == true) {
  35. //这里是上传成功后,所需要执行的逻辑代码
  36. return "上传成功!";
  37. }
  38. }
  39. return "上传失败,文件不能为空!";
  40. } catch (Exception e) {
  41. return "上传异常,请重试!";
  42. }
  43. }
  44. }

4.2 页面代码

  1. <body>
  2. <form action="/api/uploadFile" method="post" enctype="multipart/form-data">
  3. <input id="file" name="file" type="file" multiple="multiple" style="margin:100px;"/>
  4. <input type="submit" value="上传">
  5. </form>
  6. </body>

在浏览器输入相应的地址查看是否成功即可。

注意

如果使用yml的形式,需要导入以下依赖。

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-configuration-processor</artifactId>
  4. <optional>true</optional>
  5. </dependency>

也就是通过使用 @ConfigurationProperties(prefix = "ftp") 来获取yml自定义属性的信息。

  1. @Data
  2. @Component
  3. @ConfigurationProperties(prefix = "ftp")
  4. public Class FtProperties{
  5. private String address;
  6. private int port;
  7. private String username;
  8. private String password;
  9. }

application.yml配置

  1. ftp:
  2. address: 000.000.000.000
  3. port: 21
  4. charset: GBK
  5. username: uftp
  6. password: upwd123456

普通的文件上传,请点击查看:SpirngBoot文件上传