一、引入依赖
<!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>3.6</version>
</dependency>
二、编写配置文件
ftp:
ip: 192.168.179.8
port: 21
username: minco
password: 123
三、编写FTP配置
/**
* FTP参数配置类
*/
@Data
@Configuration
public class FtpProperties {
@Value("${ftp.ip}")
private String ip;
@Value("${ftp.port}")
private int port;
@Value("${ftp.username}")
private String username;
@Value("${ftp.password}")
private String password;
}
四、编写工具类
import com.hieasy.dataprovider.common.properties.FtpProperties;
import com.hieasy.dataprovider.common.utils.StringUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.net.ftp.*;
import java.io.*;
import java.text.SimpleDateFormat;
import java.util.Comparator;
import java.util.Properties;
import java.util.TreeSet;
/**
* @Author Minco
* @Date 16:10 2020-08-20
* @Description FtpUtils
*/
public class FtpUtils {
private static String username;
private static String password;
private static String ip;
private static int port;
private static Properties property=null;//配置
private static FTPClient ftpClient=null;
private static SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd hh:mm");
private static final String [] FILE_TYPES={"文件","目录","符号链接","未知类型"};
public static void main(String[] args) {
FtpProperties properties=new FtpProperties();
properties.setIp("192.168.179.8");
properties.setPort(21);
properties.setUsername("minco");
properties.setPassword("123");
connectServer(properties);
listAllRemoteFiles(properties);//列出所有文件和目录
changeWorkingDirectory(properties,"webroot");//进入文件夹webroot
listRemoteFiles(properties,"*.jsp");//列出webroot目录下所有jsp文件
setFileType(properties,FTP.BINARY_FILE_TYPE);//设置传输二进制文件
uploadFile(properties,"woxingwosu.xml","myfile.xml");//上传文件woxingwosu.xml,重新命名为myfile.xml
renameFile(properties,"viewDetail.jsp", "newName.jsp");//将文件viewDetail.jsp改名为newName.jsp
deleteFile(properties,"UpdateData.class");//删除文件UpdateData.class
loadFile(properties,"UpdateData.java","loadFile.java");//下载文件UpdateData.java,并且重新命名为loadFile.java
closeConnect();//关闭连接
}
/**
* 上传文件
* @param localFilePath--本地文件路径
* @param newFileName--新的文件名
*/
public static void uploadFile(FtpProperties properties,String localFilePath,String newFileName){
uploadFile( properties,null, localFilePath, newFileName);
}
public static void uploadFile(FtpProperties properties,String directory,String localFilePath,String newFileName){
connectServer(properties);
//上传文件
BufferedInputStream buffIn=null;
try{
if(StringUtils.isNotEmpty(directory)) ftpClient.changeWorkingDirectory(directory);
buffIn=new BufferedInputStream(new FileInputStream(localFilePath));
ftpClient.storeFile(newFileName, buffIn);
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(buffIn!=null)
buffIn.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 下载文件
* @param remoteFileName --服务器上的文件名
* @param localFileName--本地文件名
*/
public static void loadFile(FtpProperties properties,String remoteFileName,String localFileName){
connectServer(properties);
//下载文件
BufferedOutputStream buffOut=null;
try{
buffOut=new BufferedOutputStream(new FileOutputStream(localFileName));
ftpClient.retrieveFile(remoteFileName, buffOut);
}catch(Exception e){
e.printStackTrace();
}finally{
try{
if(buffOut!=null)
buffOut.close();
}catch(Exception e){
e.printStackTrace();
}
}
}
/**
* 列出服务器上所有文件及目录
*/
public static void listAllRemoteFiles(FtpProperties properties){
listRemoteFiles(properties,"*");
}
/**
* 列出服务器上文件和目录
* @param regStr --匹配的正则表达式
*/
@SuppressWarnings("unchecked")
public static void listRemoteFiles(FtpProperties properties,String regStr){
connectServer(properties);
try{
FTPFile[] files=ftpClient.listFiles(regStr);
if(files==null||files.length==0)
System.out.println("There has not any file!");
else{
TreeSet<FTPFile> fileTree=new TreeSet(
new Comparator(){
//先按照文件的类型排序(倒排),然后按文件名顺序排序
public int compare(Object objFile1,Object objFile2){
if(objFile1==null)
return -1;
else if(objFile2==null)
return 1;
else{
FTPFile file1=(FTPFile)objFile1;
FTPFile file2=(FTPFile)objFile2;
if(file1.getType()!=file2.getType())
return file2.getType()-file1.getType();
else
return file1.getName().compareTo(file2.getName());
}
}
}
);
for(FTPFile file:files)
fileTree.add(file);
System.out.printf("%-35s%-10s%15s%15s\n","名称","类型","修改日期","大小");
for(FTPFile file:fileTree){
System.out.printf("%-35s%-10s%15s%15s\n",iso8859togbk(file.getName()),FILE_TYPES[file.getType()]
,dateFormat.format(file.getTimestamp().getTime()),FileUtils.byteCountToDisplaySize(file.getSize()));
}
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 关闭连接
*/
public static void closeConnect(){
try{
if(ftpClient!=null){
ftpClient.logout();
ftpClient.disconnect();
}
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 设置传输文件的类型[文本文件或者二进制文件]
* @param fileType--BINARY_FILE_TYPE、ASCII_FILE_TYPE
*/
public static void setFileType(FtpProperties properties,int fileType){
try{
connectServer(properties);
ftpClient.setFileType(fileType);
}catch(Exception e){
e.printStackTrace();
}
}
/**
* 扩展使用
* @return
*/
protected static FTPClient getFtpClient(FtpProperties properties){
connectServer(properties);
return ftpClient;
}
private static void setArg(FtpProperties ftpProperties){
username=ftpProperties.getUsername();
password=ftpProperties.getPassword();
ip=ftpProperties.getIp();
port=ftpProperties.getPort();
}
public static void connectServer(FtpProperties properties) {
if (ftpClient == null) {
int reply;
try {
setArg(properties);
ftpClient=new FTPClient();
ftpClient.setDefaultPort(port);
ftpClient.configure(getFtpConfig());
ftpClient.connect(ip);
ftpClient.login(username, password);
ftpClient.setDefaultPort(port);
System.out.print(ftpClient.getReplyString());
reply = ftpClient.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftpClient.disconnect();
System.err.println("FTP server refused connection.");
}
} catch (Exception e) {
System.err.println("登录ftp服务器【"+ip+"】失败");
e.printStackTrace();
}
}
}
/**
* 进入到服务器的某个目录下
* @param directory
*/
public static void changeWorkingDirectory(FtpProperties properties,String directory){
try{
connectServer(properties);
ftpClient.changeWorkingDirectory(directory);
}catch(IOException ioe){
ioe.printStackTrace();
}
}
/**
* 返回到上一层目录
*/
public static void changeToParentDirectory(FtpProperties properties){
try{
connectServer(properties);
ftpClient.changeToParentDirectory();
}catch(IOException ioe){
ioe.printStackTrace();
}
}
/**
* 删除文件
*/
public static void deleteFile(FtpProperties properties,String filename){
try{
connectServer(properties);
ftpClient.deleteFile(filename);
}catch(IOException ioe){
ioe.printStackTrace();
}
}
/**
* 重命名文件
* @param oldFileName --原文件名
* @param newFileName --新文件名
*/
public static void renameFile(FtpProperties properties,String oldFileName,String newFileName){
try{
connectServer(properties);
ftpClient.rename(oldFileName, newFileName);
}catch(IOException ioe){
ioe.printStackTrace();
}
}
/**
* 设置FTP客服端的配置--一般可以不设置
* @return
*/
private static FTPClientConfig getFtpConfig(){
FTPClientConfig ftpConfig=new FTPClientConfig(FTPClientConfig.SYST_UNIX);
ftpConfig.setServerLanguageCode(FTP.DEFAULT_CONTROL_ENCODING);
return ftpConfig;
}
/**
* 转码[ISO-8859-1 -> GBK]
*不同的平台需要不同的转码
* @param obj
* @return
*/
private static String iso8859togbk(Object obj){
try{
if(obj==null)
return "";
else
return new String(obj.toString().getBytes("iso-8859-1"),"GBK");
}catch(Exception e){
return "";
}
}
}
import com.hieasy.dataprovider.common.annotation.Excel;
import com.hieasy.dataprovider.common.core.domain.R;
import com.hieasy.dataprovider.common.properties.FtpProperties;
import org.apache.commons.csv.CSVFormat;
import org.apache.commons.csv.CSVPrinter;
import org.apache.commons.csv.QuoteMode;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;
import java.io.*;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
/**
*
* * @projectName dp
* * @title CsvUtil
* * @package com.hieasy.dataprovider
* * @description 导出成CSV 文件工具
* * @author Minco
* * @date 2019 2019/8/14 14:18
* * @version V1.0.0
*
*/
public class CsvUtil<T>{
private final static String NEW_LINE_SEPARATOR="\n";
public Class<T> clazz;
public CsvUtil(Class<T> clazz) {
this.clazz = clazz;
}
public static CsvUtil create(){
return new CsvUtil(null);
}
/**写入csv文件
* @param headers 列头
* @param data 数据内容
* @param filePath 创建的csv文件路径
* @throws IOException **/
public static void writeCsv(String[] headers, List<String[]> data, String filePath) throws IOException {
//初始化csvformat
CSVFormat formator = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR).withQuoteMode(QuoteMode.NONE);
//创建FileWriter对象
FileWriter fileWriter=new FileWriter(filePath);
//创建CSVPrinter对象
try (CSVPrinter printer = new CSVPrinter(fileWriter, formator)) {
//写入列头数据
printer.printRecord(headers);
if (null != data) {
//循环写入数据
for (String[] lineData : data) {
printer.printRecord(lineData);
}
}
}catch (Exception e){
}
System.out.println("CSV文件创建成功,文件路径:"+filePath);
}
/**
* 导出成为CSV格式数据
* @param list 数据库查询出来的数据集合
* @param fileName 文件名称
* @param firstCondition 第一行显示内容,一般为查询条件
* @param excludeColumnName 在excel注解基础上需要排除的字段
* @param columnName 在excel注解基础上需要重写列的中文显示名的字段
* @param lastCondition 第一行显示内容,一般为合计之类的
* @return
*/
public R exportCsv(List<T> list, String fileName, List<String> firstCondition, List<String> excludeColumnName, Map<String,String> columnName, List<String> lastCondition, String suffix){
Field[] allFields = clazz.getDeclaredFields();// 得到所有定义字段
List<Field> fields = new ArrayList<Field>();
// 得到所有field并存放到一个list中.
for (Field field : allFields) {
if (field.isAnnotationPresent(Excel.class)) {
if(CollectionUtils.isEmpty(excludeColumnName)){
fields.add(field);
}else if(!CollectionUtils.isEmpty(excludeColumnName) && !excludeColumnName.contains(field.getName())){
fields.add(field);
}
}
}
R ajaxResult = null;
//创建FileWriter对象
try {
//初始化csvformat
CSVFormat formator = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);
//创建输出流
String filename = encodingFilename(fileName,suffix);
String filePath = getfile() + filename;
FileWriter fileWriter = new FileWriter(filePath);
//创建CSVPrinter流
try (CSVPrinter printer = new CSVPrinter(fileWriter, formator)){
//写入第一列条件
if(!CollectionUtils.isEmpty(firstCondition)){
printer.printRecord(firstCondition);
}
ExcelAndCsvForMat<T> tExcelAndCsvForMat = new ExcelAndCsvForMat<>();
//写入列头
Object[] transferHeader = tExcelAndCsvForMat.getTransferHeader(fields, columnName);
printer.printRecord(transferHeader);
//写入数据集
if(!CollectionUtils.isEmpty(list)){
for (T object : list){
Object[] transferRowData = tExcelAndCsvForMat.getTransferRowData(object, fields);
printer.printRecord(transferRowData);
}
}
//写入列尾部内容
if(!CollectionUtils.isEmpty(lastCondition)){
printer.printRecord(lastCondition);
}
ajaxResult = R.ok(filename);
fileWriter.close();
}catch (Exception e){
ajaxResult = R.error("导出数据失败,请联系管理员");
}
} catch (Exception e) {
ajaxResult = R.error("导出数据失败,请联系管理员");
}
return ajaxResult;
}
public R exportCsv(List<T> list, FtpProperties ftpProperties, String fileName){
String basepath=ftpProperties.getBasepath();
String charsetName=ftpProperties.getEncoding();
Field[] allFields = clazz.getDeclaredFields();// 得到所有定义字段
List<Field> fields = new ArrayList<Field>();
// 得到所有field并存放到一个list中.
List<String> fieldStrList=new ArrayList<>();
List<String> fieldNameStrList=new ArrayList<>();
for (Field field : allFields) {
Excel attr = field.getAnnotation(Excel.class);
fieldStrList.add(attr.field());
fieldNameStrList.add(attr.name());
fields.add(field);
}
R ajaxResult = null;
//创建FileWriter对象
try {
//初始化csvformat
CSVFormat formator = CSVFormat.RFC4180.withEscape(' ').withQuoteMode(QuoteMode.NONE)
.withTrim();
//创建输出流
String filePath = basepath+fileName;
OutputStream outputStream=new FileOutputStream(filePath);
OutputStreamWriter osw = new OutputStreamWriter( outputStream, charsetName);
//osw.write(new String(new byte[] { (byte) 0xEF, (byte) 0xBB,(byte) 0xBF }));
//创建CSVPrinter流
try (CSVPrinter printer = new CSVPrinter(osw, formator)){
//写入列头
if(!CollectionUtils.isEmpty(fieldStrList)){
printer.printRecord(fieldStrList);
}
if(!CollectionUtils.isEmpty(fieldNameStrList)){
//printer.printRecord(fieldNameStrList);
}
ExcelAndCsvForMat<T> tExcelAndCsvForMat = new ExcelAndCsvForMat<>();
//写入数据集
if(!CollectionUtils.isEmpty(list)){
for (T object : list){
Object[] transferRowData = tExcelAndCsvForMat.getTransferRowData(object, fields);
printer.printRecord(transferRowData);
}
}
ajaxResult = R.ok(filePath);
osw.close();
outputStream.close();
}catch (Exception e){
e.printStackTrace();
ajaxResult = R.error("导出数据失败,"+e.getMessage());
}
} catch (Exception e) {
e.printStackTrace();
ajaxResult = R.error("导出数据失败,"+e.getMessage());
}
return ajaxResult;
}
public R exportMap(List<Map<String,Object>> list, Map<String, String> columnAndChineseNameMap, String fileName,String suffix) {
R ajaxResult = null;
//创建FileWriter对象
try {
//初始化csvformat
CSVFormat formator = CSVFormat.DEFAULT.withRecordSeparator(NEW_LINE_SEPARATOR);
//创建输出流
String filename = encodingFilename(fileName,suffix);
String filePath = getfile() + filename;
FileWriter fileWriter = new FileWriter(filePath);
//创建CSVPrinter流
try (CSVPrinter printer = new CSVPrinter(fileWriter, formator )){
//写入列头
if(!ObjectUtils.isEmpty(columnAndChineseNameMap)){
List<String> head = new ArrayList<>();
for(String key: columnAndChineseNameMap.keySet()){
head.add(columnAndChineseNameMap.get(key));
}
printer.printRecord(head.toArray());
}
//写入数据集
if(!CollectionUtils.isEmpty(list)){
for (Map map : list){
List<Object> colum = new ArrayList<>();
for(String key: columnAndChineseNameMap.keySet()){
if(map.containsKey(key)){
colum.add(map.get(key));
}
}
printer.printRecord(colum.toArray(new Object[colum.size()]));
}
}
ajaxResult = R.ok(filename);
fileWriter.close();
}catch (Exception e){
ajaxResult = R.error("导出数据失败,请联系管理员");
}
} catch (Exception e) {
ajaxResult = R.error("导出数据失败,请联系管理员");
}
return ajaxResult;
}
/**
* 编码文件名
*/
public String encodingFilename(String filename,String suffix) {
filename = UUID.randomUUID().toString() + "_" + filename + "."+suffix;
return filename;
}
public String getfile() {
//return ResourceUtils.getURL("classpath:").getPath() + "static/file/";
return System.getProperty("java.io.tmpdir") + System.getProperty("file.separator");
}
public static void main(String[] args) {
String[] headers = {"名字","年龄","出生地","","小明"};
List<String[]> data = new ArrayList<>();
data.add(new String[]{"小明","22","重庆"});
data.add(new String[]{"小红","18","南充"});
data.add(new String[]{"小强","20","成都"});
/* try {
//writeCsv(headers, data, "E:/text.csv");
} catch (IOException e) {
e.printStackTrace();
}*/
}
}
五、使用
@Autowired
private FtpProperties ftpProperties;
@GetMapping("test4")
@ApiOperation(value = "测试FTP功能", notes = "")
public R testFtp() {
IPage<Spkcb> iPage=spkcbService.selectPage();
List<Spkcb> list=iPage.getRecords();
ExcelUtil<Spkcb> util = new ExcelUtil<Spkcb>(Spkcb.class);
String filename="INVSNAP"+"LWF1"+ MyDateUtil.getTime("yyyyMMdd")+".csv";
R r=util.exportCsv(list, "库存表数据",filename);
Integer code= (Integer) r.get("code");
if(code==0){
String localFilePath=ToolUtil.getDownloadPath() +(String) r.get("msg");
FtpUtils.uploadFile(ftpProperties,"Inventory",localFilePath,filename);
}
return R.ok(filename);
}
结果: