1.Maven Pom
<dependency>
<groupId>net.sourceforge.javacsv</groupId>
<artifactId>javacsv</artifactId>
<version>2.0</version>
</dependency>
<dependency>
<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
<version>1.4.1</version>
</dependency>
2.工具类
csv工具类
package com.springboot.demo.util;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.util.Collection;
import java.util.Iterator;
import com.csvreader.CsvWriter;
/**
* 类名称: CsvUtil
* 类描述: 文件操作
* 创建人:
* 创建时间:2019/8/20 18:14
* Version 1.0.0
*/
public class CsvUtil {
/**
* Description: 将List<T>类型数据以csv存储至本地
* list:list<T>
* csvFilePath: 如D:/XXX/DATA20190821.csv
* csvHeaders:表头
*/
public static <T> void writeCSV(Collection<T> list,String csvFilePath,String[] csvHeaders) {
try {
// 定义路径,分隔符,编码
CsvWriter csvWriter = new CsvWriter(csvFilePath, ',', Charset.forName("UTF-8"));
// 写表头
csvWriter.writeRecord(csvHeaders);
// 写内容
//遍历集合
Iterator<T> it = list.iterator();
while (it.hasNext()) {
T t = (T) it.next();
//获取类属性
Field[] fields = t.getClass().getDeclaredFields();
String[] csvContent=new String[fields.length];
for (short i = 0; i < fields.length; i++) {
Field field = fields[i];
String fieldName = field.getName();
String getMethodName = "get"
+ fieldName.substring(0, 1).toUpperCase()
+ fieldName.substring(1);
try {
Class tCls = t.getClass();
Method getMethod = tCls.getMethod(getMethodName,new Class[] {});
Object value = getMethod.invoke(t, new Object[] {});
if (value == null) {
continue;
}
//取值并赋给数组
String textvalue= value.toString();
csvContent[i]= textvalue;
}catch (Exception e) {
e.getStackTrace();
}
}
//迭代插入记录
csvWriter.writeRecord(csvContent);
}
csvWriter.close();
System.out.println("<--------CSV文件写入成功-------->");
} catch (IOException e) {
e.printStackTrace();
}
}
}
ftp工具类
import org.apache.commons.net.ftp.FTPClient;
import java.io.InputStream;
import java.util.ArrayList;
/**
* ftp接口定义
*/
public interface FtpInterface {
FTPClient ftp(String ip, String user, String password);
ArrayList<String[]> csv(InputStream in);
}
import com.csvreader.CsvReader;
import com.springboot.demo.util.ftp.FtpInterface;
import org.apache.commons.net.ftp.FTPClient;
import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;
import java.nio.charset.Charset;
import java.util.ArrayList;
/**
* @Author kxwang
* @Description ftp实现类
* @Date 2019/7/22 19:22
*/
public class Ftp implements FtpInterface {
/**
* <b>登陆ftp 返回ftpClient事件<b>
* @param ip ftp所在ip
* @param user 登陆名
* @param password 密码
*/
public FTPClient ftp(String ip, String user, String password) {
FTPClient ftpClient = new FTPClient();
try {
ftpClient.connect(ip);
ftpClient.login(user, password);
} catch (SocketException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
if (!ftpClient.isConnected()) {
ftpClient = null;
}
return ftpClient;
}
/**
* <b>将一个IO流解析,转化数组形式的集合<b>
*
* @param in 文件inputStream流
*/
public ArrayList<String[]> csv(InputStream in) {
ArrayList<String[]> csvList = new ArrayList<>();
if (null != in) {
CsvReader reader = new CsvReader(in, ',', Charset.forName("UTF-8"));
try {
//遍历每一行,若有#注释部分,则不处理,若没有,则加入csvList
while (reader.readRecord()) {
if (!reader.getValues()[0].contains("#"))// 清除注释部分
{
//获取的为每一行的信息,以数组的形式
csvList.add(reader.getValues());
}
}
} catch (IOException e) {
e.printStackTrace();
}
reader.close();
}
return csvList;
}
}
package com.springboot.demo.util;
import com.springboot.demo.util.ftp.FtpInterface;
import com.springboot.demo.util.ftp.Impl.Ftp;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPReply;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
/**
* 类名称: FtpUtil
* 类描述: ftp工具类
* 创建人:
* 创建时间:2019/8/19 20:38
* Version
*/
public class FtpUtil {
/**
* @Description: 传入:ip,用户名,密码,文件路径,文件名称,获取ftp文件返回数组
*/
public static ArrayList<String[]> ftpWorks(String ip, String user, String password, String dir, String fileName){
// 创建接口服务
FtpInterface ftpInterface = new Ftp();
// 登录ftp,获取事件
//FTPClient ftp1 = ftpInterface.ftp("ftp上的ip地址", "用户名", "密码");//这里是ip,用户名,密码
FTPClient ftp1 = ftpInterface.ftp(ip,user,password);//这里是ip,用户名,密码
//将ftp操作改为被动模式 否则可能有421错误。
ftp1.enterLocalPassiveMode();
ArrayList<String[]> csvList =null;
if (null != ftp1) {
try {
// 更改当前工作目录,HC2WL为文件所在的目录
ftp1.changeWorkingDirectory(dir);
// 从ftp上获取HC2WL目录下的文件
FTPFile[] file = ftp1.listFiles();
// 遍历所有文件,匹配需要查找的文件
for (int i = 0; i < file.length; i++) {
// 匹配到则进入
if (file[i].getName().contains(fileName)) {
// 将匹配到的文件流传入接口,转化成数组集合
csvList = ftpInterface.csv(ftp1.retrieveFileStream(file[i].getName()));
//处理数据
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
return csvList;
}
/**
* Description: 向FTP服务器上传文件
* @Version 1.0
* @param url FTP服务器hostname
* @param port FTP服务器端口
* @param username FTP登录账号
* @param password FTP登录密码
* @param path FTP服务器保存目录
* @param filename 上传到FTP服务器上的文件名
* @param input 输入流
* @return 成功返回true,否则返回false *
*/
public static boolean uploadFile(String url,// FTP服务器hostname
int port,// FTP服务器端口
String username, // FTP登录账号
String password, // FTP登录密码
String path, // FTP服务器保存目录
String filename, // 上传到FTP服务器上的文件名
InputStream input // 输入流
){
boolean success = false;
FTPClient ftp = new FTPClient();
ftp.setControlEncoding("GBK");
try {
int reply;
ftp.connect(url, port);// 连接FTP服务器
// 如果采用默认端口,可以使用ftp.connect(url)的方式直接连接FTP服务器
ftp.login(username, password);// 登录
reply = ftp.getReplyCode();
if (!FTPReply.isPositiveCompletion(reply)) {
ftp.disconnect();
return success;
}
ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
ftp.makeDirectory(path);
ftp.changeWorkingDirectory(path);
ftp.storeFile(filename, input);
input.close();
ftp.logout();
success = true;
} catch (IOException e) {
e.printStackTrace();
} finally {
if (ftp.isConnected()) {
try {
ftp.disconnect();
} catch (IOException ioe) {
}
}
}
return success;
}
/**
* 将本地文件上传到FTP服务器上 *
*/
public static void upLoadFromProduction(String url,// FTP服务器hostname
int port,// FTP服务器端口
String username, // FTP登录账号
String password, // FTP登录密码
String path, // FTP服务器保存目录
String filename, // 上传到FTP服务器上的文件名
String orginfilename // 输入流文件名
) {
try {
FileInputStream in = new FileInputStream(new File(orginfilename));
boolean flag = uploadFile(url, port, username, password, path,filename, in);
System.out.println(flag);
} catch (Exception e) {
e.printStackTrace();
}
}
}
3.Service(一共5步)
1.查询数据
映射对象为HCClue,查询出为List的数据
2.设置表头
表头就像excel表第一行字段说明,或者数据库的字段名
3.设置本地路径和文件名
4.存储csv到本地
5.从本地传到ftp
package com.springboot.demo.service.impl;
import com.springboot.demo.entity.HCClue;
import com.springboot.demo.mapper.WLToHCMapper;
import com.springboot.demo.service.WLToHCService;
import com.springboot.demo.util.CsvUtil;
import com.springboot.demo.util.FtpUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
/**
* 类名称: WLToHCServiceImpl
* 创建时间:2019/8/20 16:13
* Version 1.0.0
*/
@Slf4j
@Service
public class WLToHCServiceImpl implements WLToHCService {
@Autowired
private WLToHCMapper wlToHCMapper;
@Value("${FTPConfiguration.hcftp2.ftpip}")
private String ip;
@Value("${FTPConfiguration.hcftp2.port}")
private int port;
@Value("${FTPConfiguration.hcftp2.username}")
private String username;
@Value("${FTPConfiguration.hcftp2.password}")
private String password;
/**
* @Author kxwang
* @Description
* @Date 2019/8/20 16:17
* @Param []
* @return void
*/
public void SendClueToHC() {
try {
//1.查询要存储csv的数据
List<HCClue> hcClueList = wlToHCMapper.queryClueByHK();
//2.表头
String[] csvHeaders = {"POLICE_NAME","CLUE_ID","CASE_CODE","POLICE_CODE","CREATOR",
"RESOURCE_TYPE","FILE_NAME","CREATE_TIME","UPDATE_TIME","IS_DELETED","FEATURE"};
//3.设置本地路径和文件名
Calendar calendar = Calendar.getInstance();
calendar.setTime(new Date());
calendar.add(Calendar.DATE,-1);
Date time = calendar.getTime();
String date = new SimpleDateFormat("yyyyMMdd").format(time);
String filepath = "D:/WL2HC/";// D:/WL2HC/
File dirfile = new File(filepath);
if (!dirfile.exists()) {
dirfile.mkdirs();
}
String fileName = "CLUEDATA" + date + ".csv"; // DATACLUE20190821.csv
String localFileName = filepath + fileName; // D:/WL2HC/DATACLUE20190821.csv
//4.存储csv到本地
CsvUtil.writeCSV(hcClueList,localFileName,csvHeaders);
//5.从本地传到ftp
FtpUtil.upLoadFromProduction(ip,port,username,password,"/WL2HC/",fileName,localFileName);
} catch (Exception e) {
log.error("csv本地保存失败",e);
}
}
}
mapper、mapper.xml省略…
4.测试
测试样例:
package com.springboot.demo;
import com.springboot.demo.service.WLToHCService;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootdemoApplication.class,webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
public class test10 {
@Autowired
private WLToHCService wlToHCService;
/**
* Description: 测试写入csv文件并存储本地,再使用FTP上传
*/
@Test
public void SendClueToHC(){
try {
wlToHCService.SendClueToHC();
} catch (Exception e) {
e.printStackTrace();
}
}
}
执行测试,文件已存储到本地
查看ftp服务器上文件夹下csv文件
结束
.
.
.
补充:如果需要删除本地文件,保存本地和发送ftp后,try-cach-finally中finally里面关流后删除文件夹
上述代码中修改:WLToHCServiceImpl 类的SendClueToHC方法try-cach加finally
try {
//...
} catch (IOException e) {
log.error("", e);
} finally {
File delFile = new File(filepath);
FileUtils.deleteDirectories(delFile);
}
工具类:删除目录下所有文件夹及文件
package com.xforwardai.battlemap.util;
import java.io.File;
import java.util.List;
public class FileUtils {
// 删除文件夹下所有文件
public static void deleteFiles(File rootFile) { //参数是根文件夹
if (rootFile.listFiles().length == 0) {// 如果用户给定的是空文件夹就退出方法
return;//退出
} else {
File[] files = rootFile.listFiles();// 将非空文件夹转换成File数组
for (File file : files) {//使用foreach语句遍历文件数组
if (file.isFile()) {//判断是否为文件
file.delete();// 删除指定文件夹下的所有文件
} else {
if (file.listFiles().length == 0) {//file类型是文件夹且文件夹为空
file.delete();// 删除指定文件夹下的所有空文件夹
} else {
deleteDirectories(file);// 删除指定文件夹下的所有非空文件夹(包括file)
}
}
}
}
}
// 删除文件夹及文件夹下所有文件
public static void deleteDirectories(File rootFile) {
if (rootFile.isFile()) {//第一次肯定不是文件类型,因为deleteFiles方法中已经判断过了
rootFile.delete();// 如果给定的File对象是文件就直接删除
} else {// 如果是一个文件夹就将其转换成File数组
File[] files = rootFile.listFiles();// 将非空文件夹转换成File数组
for (File file : files) {//使用foreach语句遍历文件数组
deleteDirectories(file);// 如果不是空文件夹则就迭代deleteDictionary()方法
}
rootFile.delete();// 如果是空文件夹就直接删除
}
}
// 获得指定目录下的所有文件的路径
public static List<String> getFilePath(List<String> list, File rootFile) {//返回值的就是传入的List<String> list类型,用于输出被删除的文件
File[] files = rootFile.listFiles();// 将非空文件夹转换成File数组
for (File file : files) {//使用foreach语句遍历文件数组
if (file.isDirectory()) {//判断是否为文件夹
getFilePath(list, file);//如果是文件夹则就迭代getFilePath()方法
} else {
//添加file的绝对路径添加到list中,在 UNIX 系统上,此字段的值为 '/';在 Microsoft Windows 系统上,它为 '\'
list.add(file.getAbsolutePath().replace("\\", File.separator));
}
}
//返回所有文件路径,我利用自动生成的文件夹程序,然后再删除发现文本域没输出,原来获得的只是文件路径,我花了半小时找题,被自己蠢哭
return list;//文件的路径是文件!文件!文件!
}
}