第一步:获取到上传的文件
@RequestMapping(value = "/xxx",produces = {"application/json;charset=UTF-8"})
public Response import(MultipartFile file) throws Exception {}
第二步:获取文件流
//InputStream=file.getInputStream()
public static Pair<Integer,Map<String,List<Object>>> importDataV2(InputStream in,List<String> readFileName){
Map<String,List<Object>> map = new HashMap<>();
//总数据条数
int count = 0;
ZipInputStream zin = new ZipInputStream(in);
ZipEntry ze;
try {
//读取一个文件
while((ze = zin.getNextEntry()) != null){
//为了防止用户导入时选择了错误的文件影响其他表的数据,做一层过滤
if(!readFileName.contains(ze.getName())){
log.warn("导入文件与接口不符,文件名:{}",ze.getName());
continue;
}
if(ze.isDirectory()){
//为空的文件夹什么都不做
}else{
BufferedReader br = new BufferedReader(new InputStreamReader(zin, StandardCharsets.UTF_8));
List<Object> list = new ArrayList<>();
int cnt = readCsvFileV2(br, ze.getName(),list);
count+=cnt;
//list里面就是组装好的对象list了
map.put(ze.getName(),list);
}
}
return Pair.of(count,map);
}catch (HsjryException e){
throw e;
}catch (Exception e){
e.printStackTrace();
log.error(e,"importDataError");
}finally {
try{
zin.close();
}catch(Exception e){
e.printStackTrace();
}
}
return null;
}
第三步:读取每一行数据,并转化为对象
- 根据文件名判断对数据进行组装为对象
private static int readCsvFileV2(BufferedReader br, String name,List<Object> list) {
int count = 0;
try {
// 创建 CSV Reader 对象, 参数说明(读取的文件路径,分隔符,编码格式)
CsvReader csvReader = new CsvReader(br);
// 跳过表头
csvReader.readHeaders();
// 读取除表头外的内容,读取一行
while (csvReader.readRecord()) {
// 读取一整行
String line = csvReader.getRawRecord();
//解密
line = Objects.equals(PropertiesConfig.needEncrypt,Boolean.TRUE) ? deciphering(line) : line;
count++;
//只切割双引号外面的逗号
String[] split = line.split(",(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*$)",-1);
String newVersion = VersionUtil.getNewVersion(null);
String newTechnologyVersion = VersionUtil.getNewTechnologyVersion(newVersion);
long longId = FtSequenceTool.nextLongId();
switch (name){
case FEATURES_COM_FILE_NAME:
buildFeaturesCom(longId, newVersion, newTechnologyVersion, split,list);
break;
default:
break;
}
}
} catch (HsjryException e) {
throw e;
} catch (Exception e) {
//某一个文件出错,仅打印日志
log.error(e,"读取文件{}出错",name);
}
return count;
}
- 这里是一些默认属性的设置
3.将文件中的数据通过反射设置到对象上面
/**
* 对 object 进行属性设置
* @param object
* @param data
* @param fields
*/
public static void buildFiled(Object object, String[] data, String[] fields) {
for (int i = 0; i < fields.length; i++) {
try {
Field field = object.getClass().getDeclaredField(fields[i]);
field.setAccessible(true);
Class<?> type = field.getType();
String value = data[i];
if(NOT_NULL_FIELD.contains(field.getName()) && value==null){
throw new HsjryException("500","该列不允许为空");
}
if(value!=null && !"null".equals(value.replace("\"", "").trim())){
if(Objects.equals(type,String.class)){
if(value.length()>=2){
if(value.indexOf("\"")==0){
//去掉第一个 "
value = value.substring(1,value.length());
}
if(value.lastIndexOf("\"")==(value.length()-1)){
//去掉最后一个 "
value = value.substring(0,value.length()-1);
}
//把两个双引号换成一个双引号
value = value.replaceAll("\"\"","\"");
}
field.set(object,value.trim());
}else if(Objects.equals(type,Long.class) && !StringUtils.isEmpty(value)){
field.set(object,Long.parseLong(value.trim()));
}else if(Objects.equals(type,Integer.class) && !StringUtils.isEmpty(value)){
field.set(object,Integer.parseInt(value.trim()));
}else if(Objects.equals(type,java.util.Date.class)){
Date parse = format.parse(value);
field.set(object,parse);
}else if(Objects.equals(type,BigDecimal.class) && !StringUtils.isEmpty(value)){
field.set(object,new BigDecimal(value.trim()));
}else if(Objects.equals(type,Double.class) && !StringUtils.isEmpty(value)){
field.set(object,Double.parseDouble(value.trim()));
}else{
log.warn("未匹配到数据类型 类名:{},属性名:{},类型:{}",object.getClass().getSimpleName(),field.getName(),type.getSimpleName());
}
}
}catch (HsjryException e){
log.error(e,"不允许为空的列为空{}",object.getClass().getSimpleName());
throw e;
}catch (Exception e){
//一行数据失败,仅打印日志,不作任何处理
log.error(e,"组装数据行失败{}",object.getClass().getSimpleName());
}
}
}