导读
原本在腾讯云搭建了一台Nginx和FTP服务器,用来作为图片保存之地。
使用步骤
1、依赖
SpringBoot项目导入以下依赖。
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
2、FTP连接工厂
该连接工厂使用createFtpConnection
创建FTP连接,ftpConnectionClose
关闭FTP连接。
import lombok.Data;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
/**
* FTP连接工厂
*
* @author chaohen
* @date 2019/8/23
*/
@Data
public class FtpConnectionFactory {
private static Logger LOGGER = LoggerFactory.getLogger(FtpConnectionFactory.class);
/**
* FTP ip地址
*/
private static String address = "000.000.000.000";
/**
* FTP 端口号
*/
private static int port = 21;
/**
* FTP 设置字符集
*/
private static String charset = "GBK";
/**
* FTP 用户名
*/
private static String username = "uftp";
/**
* FTP 密码
*/
private static String password = "upwd123456";
/**
* ftpClient
*/
private static FTPClient ftpClient;
/**
* 新建FTP连接
*
* @return
*/
synchronized public static FTPClient createFtpConnection() {
if (ftpClient == null || !ftpClient.isConnected()) {
try {
ftpClient = new FTPClient();
//连接IP 如果port【端口】存在的话
ftpClient.connect(address, port);
//设置编码类型
ftpClient.setControlEncoding(charset);
//每次数据连接之前,ftpClient告诉ftp server开通一个端口来传输数据
ftpClient.enterLocalPassiveMode();
//登录
ftpClient.login(username, password);
//连接尝试后,应检查回复代码以验证
int reply = ftpClient.getReplyCode();
//没验证成功
if (!FTPReply.isPositiveCompletion(reply)) {
//断开ftp连接
ftpClient.disconnect();
return null;
}
LOGGER.info("The ftp server is successfully connected.");
} catch (Exception e) {
LOGGER.error("Failed to log in. The error message is: " + e.getMessage());
}
}
return ftpClient;
}
/**
* 关闭FTP连接 ftpClose
*/
public static void ftpConnectionClose(FTPClient ftpClient) {
if (ftpClient != null) {
if (ftpClient.isConnected()) {
try {
ftpClient.disconnect();
LOGGER.info("Ftp connection closed...");
} catch (IOException e) {
LOGGER.error("Ftp connection failed to disconnect, error message is:" + e.getMessage());
}
}
}
}
}
3、FTP上传下载工具类
里面有两个方法,uploadFile
用来上传,getFileByFtp
用来下载。
import com.heioky.filesystemupload.config.FtpConnectionFactory;
import org.apache.commons.net.ftp.FTPClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;
/**
* ftp文件上传工具类
*
* @author hanyc
* @date 2019/8/23
*/
public class FtpFileUploadUtils {
private static Logger logger = LoggerFactory.getLogger(FtpFileUploadUtils.class);
/**
* 文件上传
*
* @param remotePath 上传到远程的文件夹路径
* @param originFileName 文件名
* @param inputStream 文件流
* @return
*/
public static boolean uploadFile(String remotePath, String originFileName, InputStream inputStream) {
//连接FTP
FTPClient ftpClient = FtpConnectionFactory.createFtpConnection();
try {
// 设置文件类型(二进制)
ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
//创建文件夹,如果有的话 就不会创建,返回false
ftpClient.makeDirectory(remotePath);
// 设置上传目录
ftpClient.changeWorkingDirectory(remotePath);
//文件转移时候的一次性读取大小
ftpClient.setBufferSize(1024);
//将流写到服务器
ftpClient.storeFile(originFileName, inputStream);
inputStream.close();
//ftp服务退出
ftpClient.logout();
return true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient != null) {
FtpConnectionFactory.ftpConnectionClose(ftpClient);
}
}
return false;
}
/**
* 下载文件
*
* @param remotePath ftp上文件存放的地址 如: /img/logo.png
* @param localPath:本地存放文件的地址 如:E:\images\logo.png
*/
public static void getFileByFtp(String remotePath, String localPath) {
File localFile = new File(localPath);
OutputStream ous = null;
FTPClient ftpClient = FtpConnectionFactory.createFtpConnection();
try {
ous = new FileOutputStream(localFile);
ftpClient.retrieveFile(remotePath, ous);
} catch (FileNotFoundException e) {
e.printStackTrace();
logger.info("file not fount...");
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftpClient != null) {
FtpConnectionFactory.ftpConnectionClose(ftpClient);
}
}
}
}
4、测试
4.1 controller层代码
package com.heioky.filesystemupload.controller;
import com.heioky.filesystemupload.utils.FtpFileUploadUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.util.UUID;
/**
* 文件上传
*
* @author chaohen
* @date 2019/8/22
*/
@Controller
@RequestMapping("/api")
public class IndexController {
private static final Logger logger = LoggerFactory.getLogger(IndexController.class);
@PostMapping("/uploadFile")
@ResponseBody
public String updateAvatar(MultipartFile file) {
try {
if (!file.isEmpty()) {
//获取文件(图片或者文件)的后缀名
String suffix = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf("."));
//拼接图片或文件名称,32位随机uuid+后缀名,当然也可以使用其他方式生成
String fileName = UUID.randomUUID().toString().replace("-", "").toLowerCase() + suffix;
InputStream inputStream = file.getInputStream();
//调用ftp上传文件工具类,返回true成功,返回false失败
Boolean flag = FtpFileUploadUtils.uploadFile("/", fileName, inputStream);
if (flag == true) {
//这里是上传成功后,所需要执行的逻辑代码
return "上传成功!";
}
}
return "上传失败,文件不能为空!";
} catch (Exception e) {
return "上传异常,请重试!";
}
}
}
4.2 页面代码
<body>
<form action="/api/uploadFile" method="post" enctype="multipart/form-data">
<input id="file" name="file" type="file" multiple="multiple" style="margin:100px;"/>
<input type="submit" value="上传">
</form>
</body>
注意
如果使用yml的形式,需要导入以下依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
也就是通过使用 @ConfigurationProperties(prefix = "ftp")
来获取yml自定义属性的信息。
@Data
@Component
@ConfigurationProperties(prefix = "ftp")
public Class FtProperties{
private String address;
private int port;
private String username;
private String password;
}
application.yml配置
ftp:
address: 000.000.000.000
port: 21
charset: GBK
username: uftp
password: upwd123456
普通的文件上传,请点击查看:SpirngBoot文件上传