<dependency>
<groupId>commons-netgroupId>
<artifactId>commons-netartifactId>
<version>3.6version>
dependency>
package com.linewell.gov.hoox.utils;
import com.linewell.gov.hoox.utils.log.LogUtil;
import io.netty.util.CharsetUtil;
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
/**
* ftp上传下载工具类
* Title: FtpUtil
*
* @version 1.0
*/
@Component
public class FtpUtil2 {
//FTP服务器hostname
@Value("${X_FTP_HOST}")
private String FTP_HOST = "FTP服务器hostname";
//FTP服务器端口
@Value("${X_FTP_PORT}")
private Integer FTP_PORT = 21;
//FTP登录账号
@Value("${X_FTP_USERNAME}")
private String FTP_USERNAME = "登录账号";
//FTP登录密码
@Value("${X_FTP_PASSWORD}")
private String FTP_PASSWORD = "登录密码";
/**
* Description: 向FTP服务器上传文件
*
* @param basePath FTP服务器基础目录 (特别注意,该基础目录不要传值)
* @param filePath FTP服务器文件存放路径。例如分日期存放:/2015/01/01。文件的路径为basePath+filePath
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false
*/
public boolean uploadFile(String basePath, String filePath, String filename, InputStream input) {
//默认用/
basePath ="/";
boolean result = false;
FTPClient ftp = new FTPClient();
//设置字符编码
ftp.setAutodetectUTF8(true);
ftp.setCharset(CharsetUtil.UTF_8);
ftp.setControlEncoding(CharsetUtil.UTF_8.name());
LogUtil.info("==(上传操作)==");
LogUtil.info("FTP服务器hostname"+FTP_HOST+"FTP服务器端口:"+FTP_PORT);
//LogUtil.info("FTP服务器账号"+FTP_USERNAME+"FTP服务器密码:"+FTP_PASSWORD);
try {
int reply;
ftp.connect(FTP_HOST, FTP_PORT);// 连接FTP服务器
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(FTP_USERNAME, FTP_PASSWORD);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
LogUtil.info("==已连接成功(上传操作)==创建目录中==");
LogUtil.info("==已连接成功(上传操作)==basePath=="+basePath);
LogUtil.info("==已连接成功(上传操作)==filePath=="+filePath);
//切换到上传目录
if (!ftp.changeWorkingDirectory(basePath + filePath)) {
//如果目录不存在创建目录
String[] dirs = filePath.split("/");
String tempPath = basePath;
for (String dir : dirs) {
if (null == dir || "".equals(dir)) continue;
tempPath += "/" + dir;
if (!ftp.changeWorkingDirectory(tempPath)) {
if (!ftp.makeDirectory(tempPath)) {
return result;
} else {
ftp.changeWorkingDirectory(tempPath);
}
}
}
}
//设置上传文件的类型为二进制类型
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//上传文件
if (!ftp.storeFile(filename, input)) {
return result;
}
LogUtil.info("==已连接成功(上传操作)==流关闭==");
input.close();
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* Description: 从FTP服务器下载文件
*
* @param remotePath FTP服务器上的相对路径
* @param fileName 要下载的文件名
* @param localPath 下载后保存到本地的路径
* @return
*/
public boolean downloadFile(String remotePath,
String fileName, String localPath) {
boolean result = false;
FTPClient ftp = new FTPClient();
//设置字符编码
ftp.setAutodetectUTF8(true);
ftp.setCharset(CharsetUtil.UTF_8);
ftp.setControlEncoding(CharsetUtil.UTF_8.name());
try {
int reply;
ftp.connect(FTP_HOST, FTP_PORT);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(FTP_USERNAME, FTP_PASSWORD);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
ftp.changeWorkingDirectory(remotePath);// 转移到FTP服务器目录
FTPFile[] fs = ftp.listFiles();
for (FTPFile ff : fs) {
if (ff.getName().equals(fileName)) {
File localFile = new File(localPath + "/" + ff.getName());
OutputStream is = new FileOutputStream(localFile);
ftp.retrieveFile(ff.getName(), is);
is.close();
}
}
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* Description: 从FTP服务器下载文件的浏览器上面
* (注意前端调用需要http请求,ajax请求不支持流的下载)
*
* @param ftpFilePath ftp服务器上面的位置
* @param fileName 文件名称
* @param response
* @return
*/
public boolean downloadFileBrowser(String ftpFilePath, String fileName, HttpServletResponse response) {
boolean result = false;
InputStream input = null;
ServletOutputStream out = null;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(FTP_HOST, FTP_PORT);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(FTP_USERNAME, FTP_PASSWORD);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
response.reset();
//此处你就根据你要下载的类型去设置即可,比如我下载.avi格式的文件,可以设置response.setContentType("video/avi");
// 设置文件ContentType类型,这样设置,会自动判断下载文件类型
response.setContentType("application/x-msdownload");
//解决中文不能生成文件(包含空格)
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(fileName, "UTF-8"));
//传输模式
ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
// 设置以二进制流的方式传输
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//进入目录
ftp.changeWorkingDirectory(ftpFilePath);
FTPFile[] files = ftp.listFiles();
if (files.length < 1) {
return result;
}
boolean fileExist = false;
boolean downloadFlag = false;
for (FTPFile ftpFile : files) {
String ftpFileName = new String(ftpFile.getName().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
if (fileName.equals(ftpFileName)) {
fileExist = true;
input = ftp.retrieveFileStream(new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
out = response.getOutputStream();
int len;
byte[] bytes = new byte[1024];
while ((len = input.read(bytes)) != -1) {
out.write(bytes, 0, len);
}
out.flush();
downloadFlag = true;
break;
}
}
if (!fileExist) {
return result;
}
return result;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* Description: 从FTP服务器下载文件的浏览器上面
* (注意前端调用需要http请求,ajax请求不支持流的下载)
*
* @param ftpFilePath ftp服务器上面的位置
* @param fileName 文件名称
* @return
*/
public InputStream downloadFileInputStream(String ftpFilePath, String fileName) {
InputStream input = null;
FTPClient ftp = new FTPClient();
try {
int reply;
ftp.connect(FTP_HOST, FTP_PORT);
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(FTP_USERNAME, FTP_PASSWORD);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return input;
}
//传输模式
ftp.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
// 设置以二进制流的方式传输
ftp.setFileType(FTP.BINARY_FILE_TYPE);
//进入目录
ftp.changeWorkingDirectory(ftpFilePath);
FTPFile[] files = ftp.listFiles();
if (files.length < 1) {
return input;
}
boolean fileExist = false;
for (FTPFile ftpFile : files) {
String ftpFileName = new String(ftpFile.getName().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
if (fileName.equals(ftpFileName)) {
fileExist = true;
input = ftp.retrieveFileStream(new String(fileName.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1));
break;
}
}
if (!fileExist) {
return input;
}
return input;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return input;
}
/**
* 删除ftp上面的文件
* @param pathname FTP服务器保存目录
* @param filename 要删除的文件名称
* @return
*/
public boolean deleteFile(String pathname, String filename){
boolean result = false;
FTPClient ftp = new FTPClient();
//设置字符编码
ftp.setAutodetectUTF8(true);
ftp.setCharset(CharsetUtil.UTF_8);
ftp.setControlEncoding(CharsetUtil.UTF_8.name());
try {
int reply;
ftp.connect(FTP_HOST, FTP_PORT);// 连接FTP服务器
// 如果采用默认端口,可以使用ftp.connect(host)的方式直接连接FTP服务器
ftp.login(FTP_USERNAME, FTP_PASSWORD);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return result;
}
//切换FTP目录
ftp.changeWorkingDirectory(pathname);
ftp.dele(filename);
ftp.logout();
result = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return result;
}
/**
* 测试
*
* @param args
*/
public static void main(String[] args) {
try {
FileInputStream in = new FileInputStream(new File("C:\\Users\\HONOR\\Desktop\\1.jpeg"));
//boolean flag = uploadFile("", "/2022/01", "holle.jpg", in);
//boolean flag2 = downloadFile("/ftp_data/images", "test.jpg", "/Volumes/H");
//System.out.println(flag);
} catch (Exception e) {
e.printStackTrace();
}
}
}
注意Controller类上面要加@RestController
以下接口才能被调用成功
/**
* 附件ftp上传
* @param request
* @param fileUploadRsp
* @return
*/
@Path("/attachmentUpload")
@RequestMapping("/attachmentUpload")
public String addStudentDispose(HttpServletRequest request, FileUploadRsp fileUploadRsp) {
System.out.println(request);
System.out.println(fileUploadRsp);
//再强转为文件的请求
MultipartHttpServletRequest mureq = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> files1 = mureq.getFileMap();//直接获取map文件集合
//创建新文件集合
List<MultipartFile> filelist = new ArrayList<>();
//循化增加
for (Map.Entry<String, MultipartFile> f : files1.entrySet()) {
System.out.println(f.getKey());
filelist.add(f.getValue());
}
for (MultipartFile mfile : filelist) {
//文件名称
System.out.println(mfile.getOriginalFilename());
}
//文件具体路径
//由于是liunx上面的ftp服务器,所以直接使用“/”
String filePath = "/" + areaid + "/" + deptid + "/" + p1 + "/" + bsnum;
//在加一个前缀
filePath="/" +"DZGD_QTFJ"+"/"+filePath;
String dirPath = rootPath + filePath;
//开始保存文件到本地
for (MultipartFile mfile : filelist) {
//保存本地
//File file = multipartFile2File(dirPath + File.separator + mfile.getOriginalFilename(), mfile);
try {
//保存ftp
ftpUtil2.uploadFile("",filePath, mfile.getOriginalFilename(), mfile.getInputStream());
//文件保存以后,同时也要存记录到库
} catch (Exception e) {
e.printStackTrace();
}
}
return "成功";
}
/**
* ftp附件下载
* @param request
* @param fileid 附件id
* @param response
* @return
*/
@Path("/attachmentDownload")
@RequestMapping("/attachmentDownload")
@Transactional()
public String addStudentDispose(HttpServletRequest request,String fileid,HttpServletResponse response) {
//查询
GInsFjinfoDO infoById = gInsFjinfoDao.getInfoById(fileid);
//保存ftp
ftpUtil2.downloadFileBrowser(infoById.getFjwz(),infoById.getFjmc(),response);
return null;
}