diff --git a/eladmin-common/src/main/java/me/zhengjie/common/http/ResponseCode.java b/eladmin-common/src/main/java/me/zhengjie/common/http/ResponseCode.java index 370e385..102572e 100644 --- a/eladmin-common/src/main/java/me/zhengjie/common/http/ResponseCode.java +++ b/eladmin-common/src/main/java/me/zhengjie/common/http/ResponseCode.java @@ -23,6 +23,7 @@ public enum ResponseCode { NO_FILE_INPUT(1,"没有文件输入"), // 特殊需要进行前端返回说明的参数定义 TASK_NAME_IS_EXIST(1,"任务名称已经存在"), + TASK_FILE_SAVE_FAIL(1,"文件存储失败"), ONCE_LINK_MSG_ERROR(1,"链接失效,下载文件失败~"), // 请求结果性的错误 NODATA_ERROR(1,"查询结果为空"), diff --git a/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java b/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java index f0f3100..76aa121 100644 --- a/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java +++ b/eladmin-common/src/main/java/me/zhengjie/utils/StringUtils.java @@ -20,6 +20,7 @@ import cn.hutool.json.JSONObject; import cn.hutool.json.JSONUtil; import eu.bitwalker.useragentutils.Browser; import eu.bitwalker.useragentutils.UserAgent; +import org.apache.poi.ss.formula.functions.T; import org.lionsoul.ip2region.DataBlock; import org.lionsoul.ip2region.DbConfig; import org.lionsoul.ip2region.DbSearcher; @@ -33,6 +34,7 @@ import java.net.InetAddress; import java.net.UnknownHostException; import java.util.Calendar; import java.util.Date; +import java.util.List; /** * @author Zheng Jie @@ -66,6 +68,22 @@ public class StringUtils extends org.apache.commons.lang3.StringUtils { }); } + /** + * list -> string 无 [], 无 空格 + * + * @param list 需要进行格式化打印的 list + * @param specialTag 分隔的特殊字符 + * @return 打印输出 + */ + public static String listPrintWithSpecialSplit(List list, String specialTag){ + String str = list.toString().replaceAll("(?:\\[|null|]| +)", ""); + + if (StringUtils.isNotBlank(specialTag)){ + return str.replaceAll(",", specialTag); + } + return str; + } + /** * 驼峰命名法工具 * diff --git a/eladmin-system/doc/rules.md b/eladmin-system/doc/rules.md new file mode 100644 index 0000000..85f04b3 --- /dev/null +++ b/eladmin-system/doc/rules.md @@ -0,0 +1,10 @@ +# 上传文件的路径格式定义 + 项目基础的存放规则路径(必须要以/来结束) + 时间(2021-2-2) + 文件名(6位随机字符串_原始文件名.txt) + + 规范定义总目录 + 上传的具体时间 + 随机字符加分隔符加原始文件名和后缀组成 + + + + + + \ No newline at end of file diff --git a/eladmin-system/pom.xml b/eladmin-system/pom.xml index bca08a7..2b09377 100644 --- a/eladmin-system/pom.xml +++ b/eladmin-system/pom.xml @@ -86,6 +86,11 @@ oshi-core 5.0.1 + + com.google.guava + guava-parent + 23.0 + diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/consts/SysConst.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/consts/SysConst.java new file mode 100644 index 0000000..370b65d --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/consts/SysConst.java @@ -0,0 +1,24 @@ +package me.zhengjie.modules.upload.consts; + +/** + * 系统相关的配置 + */ +public class SysConst { + + // 远程服务器的相关配置 + public static final String REMOTE_TRANS_HOST = "47.110.11.213"; + + public static final Integer REMOTE_TRANS_PORT = 22; + + public static final String REMOTE_TRANS_SSH_USER = "root"; + + public static final String REMOTE_TRANS_SSH_PW = "yuyou@ECS2020"; + + public static final String REMOTE_TRANS_DIR_PATH = "/home"; + + // fixme 以后改成rpc调用的地址 + public static final String REMOTE_UPDATE_ADDR = "http://116.62.197.152:8000/api/"; + + // 测试内容临时定义 + public static final String TEST_USER_NAME = "测试用户"; +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/consts/UploadFileConst.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/consts/UploadFileConst.java index f5017ae..b21cf19 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/upload/consts/UploadFileConst.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/consts/UploadFileConst.java @@ -19,4 +19,20 @@ public class UploadFileConst { * 正在执行的标识 */ public static final Integer DOING_TAG = 1; + + /** + * 成功执行的标识 + */ + public static final Integer SUCCESS_TAG = 0; + + /** + * 失败执行的标识 + */ + public static final Integer FAIL_TAG = 2; + + + /** + * 文件名的分隔符 _ + */ + public static final String FILE_NAME_SPLIT = "_"; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/domain/UploadFile.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/domain/UploadFile.java index ecde38c..bc7b0e0 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/upload/domain/UploadFile.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/domain/UploadFile.java @@ -45,7 +45,7 @@ public class UploadFile implements Serializable { @ApiModelProperty(value = "上传日期") private Timestamp uploadTime; - @Column(name = "opration") + @Column(name = "operation") @ApiModelProperty(value = "操作人") private String opration; diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/rest/UploadFileController.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/rest/UploadFileController.java index 426de6e..143794c 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/upload/rest/UploadFileController.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/rest/UploadFileController.java @@ -15,13 +15,17 @@ */ package me.zhengjie.modules.upload.rest; +import lombok.extern.slf4j.Slf4j; import me.zhengjie.annotation.AnonymousAccess; import me.zhengjie.annotation.Log; import me.zhengjie.common.http.CommonResponse; import me.zhengjie.common.http.ResponseCode; import me.zhengjie.modules.upload.domain.UploadFile; import me.zhengjie.modules.upload.service.UploadFileService; +import me.zhengjie.modules.upload.service.dto.UploadFileDto; import me.zhengjie.modules.upload.service.dto.UploadFileQueryCriteria; +import me.zhengjie.modules.upload.task.SaveToFileTask; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.data.domain.Pageable; import lombok.RequiredArgsConstructor; import org.springframework.http.HttpStatus; @@ -33,6 +37,7 @@ import io.swagger.annotations.*; import org.springframework.web.multipart.MultipartFile; import java.io.IOException; +import java.util.Objects; import javax.servlet.http.HttpServletResponse; /** @@ -44,10 +49,14 @@ import javax.servlet.http.HttpServletResponse; @RequiredArgsConstructor @Api(tags = "上传文件解析发送管理") @RequestMapping("/api/uploadFile") +@Slf4j public class UploadFileController { private final UploadFileService uploadFileService; + @Autowired + private SaveToFileTask saveToFileTask; + @Log("导出数据") @ApiOperation("导出数据") @GetMapping(value = "/download") @@ -103,7 +112,15 @@ public class UploadFileController { return new ResponseEntity<>(CommonResponse.createByError(ResponseCode.NO_FILE_INPUT), HttpStatus.OK); } // 生成本地文件 - uploadFileService.encryptDataAndSaveToFile(files); + UploadFileDto uploadFileDto = uploadFileService.encryptDataAndSaveToFile(files); + + // 如果临时生成失败就修改状态为失败 + if (Objects.isNull(uploadFileDto)){ + log.error("UploadFileController:sendTask | Operation Fail.UploadFile is Null"); + return new ResponseEntity<>(CommonResponse.createByError(ResponseCode.TASK_FILE_SAVE_FAIL), HttpStatus.OK); + } + // 调用异步任务 + saveToFileTask.doRunTask(uploadFileDto); return new ResponseEntity<>(CommonResponse.createBySuccess(ResponseCode.SUCCESS), HttpStatus.OK); } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/script/trans.sh b/eladmin-system/src/main/java/me/zhengjie/modules/upload/script/trans.sh new file mode 100644 index 0000000..dc53c5f --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/script/trans.sh @@ -0,0 +1,8 @@ +#!/bin/bash +# please make the rsa key first + +read line < + +scp -i ~/.ssh/id_rsa devops@myserver.org:/path/to/bin/*.derp . + + diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/UploadFileService.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/UploadFileService.java index edd48da..f348279 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/UploadFileService.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/UploadFileService.java @@ -88,5 +88,5 @@ public interface UploadFileService { * * @param files */ - void encryptDataAndSaveToFile(MultipartFile[] files); + UploadFileDto encryptDataAndSaveToFile(MultipartFile[] files); } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/dto/UploadFileDto.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/dto/UploadFileDto.java index c5544be..c5713c9 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/dto/UploadFileDto.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/dto/UploadFileDto.java @@ -15,7 +15,10 @@ */ package me.zhengjie.modules.upload.service.dto; +import io.swagger.annotations.ApiModelProperty; import lombok.Data; + +import javax.persistence.Column; import java.sql.Timestamp; import java.io.Serializable; @@ -35,7 +38,7 @@ public class UploadFileDto implements Serializable { private Timestamp uploadTime; /** 操作人 */ - private String opration; + private String operation; /** 文件解析总数 */ private Long fileCount; @@ -45,4 +48,7 @@ public class UploadFileDto implements Serializable { /** 上传状态 */ private Integer uploadTag; + + /** 上传保存路径 */ + private String localSavePath; } \ No newline at end of file diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/impl/UploadFileServiceImpl.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/impl/UploadFileServiceImpl.java index 862c715..3f98222 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/impl/UploadFileServiceImpl.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/service/impl/UploadFileServiceImpl.java @@ -41,10 +41,12 @@ import org.springframework.data.domain.Page; import org.springframework.data.domain.Pageable; import org.springframework.web.multipart.MultipartFile; +import java.text.SimpleDateFormat; import java.util.*; import java.io.IOException; import javax.servlet.http.HttpServletResponse; +import static me.zhengjie.modules.upload.consts.SysConst.TEST_USER_NAME; import static me.zhengjie.modules.upload.consts.UploadFileConst.*; @@ -87,8 +89,6 @@ public class UploadFileServiceImpl implements UploadFileService { private final UploadFileRepository uploadFileRepository; private final UploadFileMapper uploadFileMapper; - @Autowired - private SaveToFileTask saveToFileTask; @Override public Map queryAll(UploadFileQueryCriteria criteria, Pageable pageable) { @@ -137,7 +137,7 @@ public class UploadFileServiceImpl implements UploadFileService { for (UploadFileDto uploadFile : all) { Map map = new LinkedHashMap<>(); map.put("上传日期", uploadFile.getUploadTime()); - map.put("操作人", uploadFile.getOpration()); + map.put("操作人", uploadFile.getOperation()); map.put("文件解析总数", uploadFile.getFileCount()); map.put("上传成功总数", uploadFile.getFileTransSuccessCount()); map.put("上传状态", uploadFile.getUploadTag()); @@ -147,7 +147,7 @@ public class UploadFileServiceImpl implements UploadFileService { } @Override - public void encryptDataAndSaveToFile(MultipartFile[] files) { + public UploadFileDto encryptDataAndSaveToFile(MultipartFile[] files) { // 1. 文件存储到本地 long count = 0; // 统计总数 String baseStr = RandomUtil.randomString(11) + File.separator; // 生成通用随机文件夹存放每次的文件 @@ -161,6 +161,7 @@ public class UploadFileServiceImpl implements UploadFileService { } String extName = FileUtil.extName(originalFilename); + baseStr += baseStr + FileUtil.mainName(originalFilename); String eachFilePath = buildFileWritePath(baseStr, extName); try { // 把文件保存到本地路径 @@ -182,7 +183,11 @@ public class UploadFileServiceImpl implements UploadFileService { // 2. 更新上传记录为正在上传,解析了有多少条 UploadFile uploadFile = new UploadFile(); uploadFile.setUploadTime(new Timestamp(new Date().getTime())); - uploadFile.setOpration("");//fixme 这边补充一下需要的操作人 + String currentUsername = SecurityUtils.getCurrentUsername(); + if (StringUtils.isBlank(currentUsername)){ + uploadFile.setOpration(TEST_USER_NAME);//fixme 这边补充一下需要的操作人 + } + uploadFile.setOpration(currentUsername);//fixme 这边补充一下需要的操作人 uploadFile.setFileCount(count); uploadFile.setFileTransSuccessCount(0L); uploadFile.setUploadTag(DOING_TAG); @@ -191,13 +196,9 @@ public class UploadFileServiceImpl implements UploadFileService { uploadFile.setLocalSavePath(tempFilesPath); // 去掉最后的那个通配符 FILE_PATH_SPLIT } - UploadFile save = uploadFileRepository.save(uploadFile); - // 2.1 如果临时生成失败就修改状态为失败 - if (Objects.isNull(save)){ - log.error("UploadFileServiceImpl:encryptDataAndSaveToFile | Operation Fail.UploadFile is Null"); - } - // 3. 调用异步任务 - saveToFileTask.doRunTask(tempFilesPath); + UploadFileDto uploadFileDto = create(uploadFile); + + return uploadFileDto; } @@ -207,19 +208,22 @@ public class UploadFileServiceImpl implements UploadFileService { private String buildFileWritePath(String baseStr, String extName) { // 获取环境配置信息 OsInfo osInfo = SystemUtil.getOsInfo(); + // 定义的时间格式 + String timeFormate = new SimpleDateFormat("yyyy-MM-dd").format(new Date()); + // 生成一个随机文件夹目录,方便整理和打包 if (osInfo.isWindows()) { FileUtil.mkdir(remoteLinkFileBasePathWindows + baseStr); // 构建存储文件 - return remoteLinkFileBasePathWindows + baseStr + RandomUtil.randomString(11) + FILE_SPLIT + extName; + return remoteLinkFileBasePathWindows + File.separator + timeFormate + File.separator + RandomUtil.randomString(6) +FILE_NAME_SPLIT + baseStr + FILE_SPLIT + extName; } else if (osInfo.isLinux()) { FileUtil.mkdir(remoteLinkFileBasePathLinux + baseStr); // 构建存储文件 - return remoteLinkFileBasePathLinux + baseStr + RandomUtil.randomString(11) + FILE_SPLIT + extName; + return remoteLinkFileBasePathLinux + File.separator + timeFormate + File.separator + RandomUtil.randomString(6) + FILE_NAME_SPLIT + baseStr + FILE_SPLIT + extName; } else if (osInfo.isMac()) { FileUtil.mkdir(remoteLinkFileBasePathMac + baseStr); // 构建存储文件 - return remoteLinkFileBasePathMac + baseStr + RandomUtil.randomString(11) + FILE_SPLIT + extName; + return remoteLinkFileBasePathMac + File.separator + timeFormate + File.separator + RandomUtil.randomString(6) + FILE_NAME_SPLIT + baseStr + FILE_SPLIT + extName; } else { return ""; } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/SaveToFileTask.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/SaveToFileTask.java index 3169a49..5e764c4 100644 --- a/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/SaveToFileTask.java +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/SaveToFileTask.java @@ -1,25 +1,96 @@ package me.zhengjie.modules.upload.task; +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.codec.Base64; +import cn.hutool.core.collection.CollectionUtil; +import cn.hutool.core.util.RandomUtil; +import cn.hutool.crypto.SecureUtil; +import cn.hutool.extra.ssh.JschUtil; +import cn.hutool.extra.ssh.Sftp; +import cn.hutool.http.HttpRequest; +import cn.hutool.http.HttpResponse; +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.google.common.collect.Lists; +import com.jcraft.jsch.Session; +import com.mchange.v2.beans.BeansUtils; import lombok.extern.slf4j.Slf4j; +import me.zhengjie.modules.upload.domain.UploadFile; +import me.zhengjie.modules.upload.service.UploadFileService; +import me.zhengjie.modules.upload.service.dto.UploadFileDto; +import me.zhengjie.modules.upload.task.model.ResponseEncryptJsonContent; +import me.zhengjie.modules.upload.task.model.SendEncryptJsonContent; +import me.zhengjie.modules.upload.task.model.SendRemoteUpdateJsonContent; import me.zhengjie.utils.ConvertUtil; +import me.zhengjie.utils.DateUtil; +import me.zhengjie.utils.FileUtil; +import me.zhengjie.utils.StringUtils; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Scope; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; +import java.beans.Beans; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.nio.file.StandardOpenOption; import java.time.LocalDateTime; import java.time.ZoneOffset; +import java.util.Arrays; +import java.util.List; + +import static me.zhengjie.modules.upload.consts.SysConst.*; +import static me.zhengjie.modules.upload.consts.UploadFileConst.*; @Component @Scope("prototype") @Slf4j public class SaveToFileTask { + /** + * 调用加密接口的加密内容数量限制 + */ + private final static int SEND_ENCRYPT_LIMIT = 200; + + /** + * 时间格式 + */ + private final static String FORMATE_TIMESTAMP = "yyyyMMddHHmmss"; + + /** + * 分割标识 - 逗号 + */ + private static final String SPLIT_TAG = ","; + + // FIXME: 2021/1/5 0005 传输相关的配置 - 不要写在代码中,想办法进行加密 + + /** + * 加密请求需要的各种配置信息 + */ + @Value(value = "${inter.address}") + private String encryptAddress; + + @Value(value = "inter.appid") + private String encryptAppId; + + @Value(value = "inter.tk") + private String encryptTK; + + + @Autowired + private UploadFileService uploadFileService; + + + @Async(value = "SendBigDataTaskExecutor") - public void doRunTask(String tempFilesPath){ + public void doRunTask(UploadFileDto uploadFileDto) { Long satrtMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); log.info("====== [ task start running, task name is {} ] ======", "SendBigDataTask"); - runTask(tempFilesPath); + runTask(uploadFileDto); Long endMilliSecond = LocalDateTime.now().toInstant(ZoneOffset.of("+8")).toEpochMilli(); log.info("====== [ task start end, task name is {},cost milliSecond is {} ] ======", "SendBigDataTask", ConvertUtil.secondToTime(endMilliSecond - satrtMilliSecond)); } @@ -27,22 +98,223 @@ public class SaveToFileTask { /** * 执行异步任务 * - * @param tempFilesPath 上传的多个临时文件路径, + * @param uploadFileDto 需要传输用到的Bean */ - private void runTask(String tempFilesPath) { - // 4. 调用加密接口进行加密 + private void runTask(UploadFileDto uploadFileDto) { + + boolean finalTag = false; + // 获取需求的地址 + String tempFilesPath = uploadFileDto.getLocalSavePath(); + + if (StringUtils.contains(tempFilesPath, FILE_PATH_SPLIT)) { + // 多文件分文件分别进行处理 + String[] split = StringUtils.split(tempFilesPath, FILE_PATH_SPLIT); + if (split.length > 0) { + for (String eachPath : split) { + finalTag = handleEachFileContent(eachPath, uploadFileDto); + } + } + } else { + // 单文件处理 + finalTag = handleEachFileContent(tempFilesPath, uploadFileDto); + } + + // 更新状态为成功,更新解析成功的条数 + UploadFile uploadFile = new UploadFile(); + if (finalTag){ + BeanUtils.copyProperties(uploadFileDto, uploadFile); + uploadFile.setUploadTag(SUCCESS_TAG); + uploadFileService.update(uploadFile); + }else { + // 失败进行容错 + BeanUtils.copyProperties(uploadFileDto, uploadFile); + uploadFile.setUploadTag(FAIL_TAG); + uploadFileService.update(uploadFile); + } + } + + /** + * 对每一个文件的处理操作 + * + * @param filePath 进行操作的每一个文件的路径 + */ + private boolean handleEachFileContent(String filePath, UploadFileDto uploadFileDto) { + List fileAllLinesList = FileUtil.readLines(filePath, "utf-8"); + if (CollectionUtil.isNotEmpty(fileAllLinesList)) { + // 分批调用接口进行加密 + batchSendToEncrypt(fileAllLinesList); + } + + // 把临时存储的文件进行删除 + boolean delFileTag = delTempSaveFile(filePath); + + // 文件传输给2号库服务器 - 走sftp协议 - 支持断点续传 + transFileToOtherServer(filePath); + + // 调用远程接口完成一条记录更新 + boolean sendUpdatePostReqTag = sendUpdatePostReq(filePath, uploadFileDto); + // fixme 这里要修改之前的平台给一个更新接口,然后这边可以用rpc调用,也可以用http,也可以考虑直接消息中间件进行解耦 + if (delFileTag && sendUpdatePostReqTag){ + return Boolean.TRUE; + } + return Boolean.FALSE; + } + + + private void transFileToOtherServer(String filePath) { + Session session = JschUtil.getSession(REMOTE_TRANS_HOST, REMOTE_TRANS_PORT, REMOTE_TRANS_SSH_USER, REMOTE_TRANS_SSH_PW); + + Sftp sftp = JschUtil.createSftp(session); + +//fixme sftp.put("C:\\Users\\Administrator\\Desktop\\233.txt", "/home", Sftp.Mode.RESUME); + sftp.put(filePath, REMOTE_TRANS_DIR_PATH, Sftp.Mode.RESUME); + + sftp.close(); + } + + private boolean delTempSaveFile(String tempFilesPath) { + boolean del = FileUtil.del(tempFilesPath); + if (del){ + log.info("======== [success del file, file path is {} ] ========", tempFilesPath); + return Boolean.TRUE; + }else { + log.error("======== [fail del file, file path is {} ] ========", tempFilesPath); + return Boolean.FALSE; + } + } + + private void batchSendToEncrypt(List fileAllLinesList) { + List> partition = Lists.partition(fileAllLinesList, SEND_ENCRYPT_LIMIT); + + partition.forEach( + list -> { + // 装配需要的Json参数 + SendEncryptJsonContent sendEncryptJsonContent = new SendEncryptJsonContent(); + //fixme 还有一个过期时间参数为选填参数,暂时不做设置 + String tels = StringUtils.listPrintWithSpecialSplit(list, null); + sendEncryptJsonContent.setTels(Base64.encode(tels)); + sendEncryptJsonContent.setReqId(RandomUtil.randomString(10)); + sendEncryptJsonContent.setAppId(encryptAppId); + // 配置 sign + String signStr = makeSign(); + if (StringUtils.isBlank(signStr)) { + log.error("SaveToFileTask|makeSign fail!"); + } + sendEncryptJsonContent.setSig(signStr); + // 组装成JSON + String readSendJsonStr = JSON.toJSONString(sendEncryptJsonContent); + log.info("SaveToFileTask|batchSendToEncrypt ready send json is : {}", readSendJsonStr); + int count = 1; + while (count <= 3) { + // 调用HTTP请求发送数据 + HttpResponse httpResponse = sendPostReq(readSendJsonStr); + if (httpResponse.isOk() && httpResponse.body().contains("success")) { + log.info("========== [SaveToFileTask|batchSendToEncrypt request success, response is {} ] ==========", httpResponse.body()); + String responseStr = httpResponse.body(); + // 解析返回的结果,并写回本地 + parseResponseStr(responseStr); + break; + } else { + count++; + try { + Thread.sleep(3_0000); + } catch (InterruptedException e) { + log.error("SaveToFileTask|batchSendToEncrypt sleep ERROR. message is", e.getMessage(), e); + } + log.error("========== [SaveToFileTask|batchSendToEncrypt request fail, response is {} ] ==========", httpResponse.body()); + } + } + if (count > 3) { + log.error("========== [SaveToFileTask|batchSendToEncrypt update send status fail, url is {} ] ==========", encryptAddress); + } + + } + ); + } + + private void parseResponseStr(String responseStr) { + ResponseEncryptJsonContent responseContent = JSONArray.parseObject(responseStr, ResponseEncryptJsonContent.class); + // 处理需要的加密号串 + String tels = responseContent.getTels(); - // 4.1 失败进行容错 + String[] splitResTels = StringUtils.split(tels, SPLIT_TAG); - // 4.2 把临时存储的文件进行删除 + if (splitResTels != null && splitResTels.length > 0) { + List stringList = Arrays.asList(splitResTels); + // TODO: 2021/1/5 0005 这里保存文件的路径进行定义下 + String path = ""; + // 写入指定路径 + writeToFile(stringList, path); + } - // 4.3 更新状态为成功,更新解析成功的条数 + } - // 5. 文件传输给2号库服务器 + private void writeToFile(List collect, String fullPath) { + // 构建存储文件 + try { + if (!FileUtil.exist(fullPath)) { + Files.write(Paths.get(fullPath), collect, StandardOpenOption.CREATE_NEW); + } else { + Files.write(Paths.get(fullPath), collect, StandardOpenOption.APPEND); + } + } catch (IOException e) { + log.error("write prepare send file fail, please check param, fullPath is {}, {}", fullPath, e); + } + } + + private String makeSign() { + + String signBuilder = encryptAppId + + encryptTK + + DateUtil.localDateTimeFormat(LocalDateTime.now(), FORMATE_TIMESTAMP); + + return SecureUtil.md5(signBuilder).toUpperCase(); + } + + /** + * 调用HTTP请求发送Post请求 + * + * @param json 请求的body内容 + * @return 返回请求结果 + */ + private HttpResponse sendPostReq(String json) { + + HttpResponse httpResponse = HttpRequest + .post(encryptAddress) + .header("Content-Type", "application/json;charset=utf-8") + .body(json) + .execute(); + + return httpResponse; + } + + /** + * 调用HTTP请求发送更新记录的Post请求 + * + * @param path + * @return 返回请求结果 + */ + private boolean sendUpdatePostReq(String path, UploadFileDto uploadFileDto) { + // 构建发送参数 + SendRemoteUpdateJsonContent sendRemoteUpdateJsonContent = new SendRemoteUpdateJsonContent(); + BeanUtil.copyProperties(uploadFileDto, sendRemoteUpdateJsonContent); + // 转成Json字符串 + String readySendJson = JSON.toJSONString(sendRemoteUpdateJsonContent); - // 5.1 文件传输和记录更新() + // 发送请求 + HttpResponse httpResponse = HttpRequest + .post(REMOTE_UPDATE_ADDR) + .header("Content-Type", "application/json;charset=utf-8") + .body(readySendJson) + .execute(); + // 解析回送请求 + if (httpResponse.isOk() && httpResponse.body().contains("SUCCESS")){ + log.info("====== [success send upload record request! ]======"); + return Boolean.TRUE; + } + return Boolean.FALSE; } } diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/ResponseEncryptJsonContent.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/ResponseEncryptJsonContent.java new file mode 100644 index 0000000..7ee481f --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/ResponseEncryptJsonContent.java @@ -0,0 +1,27 @@ +package me.zhengjie.modules.upload.task.model; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + + +/** + * 返回的Json解析 + */ +@Data +@AllArgsConstructor +@NoArgsConstructor +public class ResponseEncryptJsonContent implements Serializable { + + private String result; + + private String reason; + + /** + * tels做base64解密后就是加密号码串,用逗号分隔 + */ + private String tels; + +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/SendEncryptJsonContent.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/SendEncryptJsonContent.java new file mode 100644 index 0000000..2020b49 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/SendEncryptJsonContent.java @@ -0,0 +1,53 @@ +package me.zhengjie.modules.upload.task.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.io.Serializable; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class SendEncryptJsonContent implements Serializable { + + /** + * 签名校验 + * + * sig值= MD5(开发者账户ID + 开发者账户授权令牌 + 时间戳) + * MD5值共32位(注:转成大写) + * 时间戳是当前系统时间(24小时制),格式“yyyyMMddHHmmss”。时间戳有效时间为50分钟 + */ + @JSONField(name = "sig") + private String sig; + + /** + * 开发者账号下的APP ID + */ + @JSONField(name = "appid") + private String appId; + + /** + * 请求唯一id + * 随机生成的字符串, 8~16位字符串 + */ + @JSONField(name = "req_id") + private String reqId; + + /** + * 支持批量,逗号分隔,一次最多200个,然后对整个字符串做base64加密 + */ + @JSONField(name = "tels") + private String tels; + + /** + * (非必须参数) + * 数据过期自动释放的天数 + * 默认30天,无此字段则默认30天后过期释放 + */ + @JsonIgnore + @JSONField(name = "expire_time") + private Integer expireTime; +} diff --git a/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/SendRemoteUpdateJsonContent.java b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/SendRemoteUpdateJsonContent.java new file mode 100644 index 0000000..b0af477 --- /dev/null +++ b/eladmin-system/src/main/java/me/zhengjie/modules/upload/task/model/SendRemoteUpdateJsonContent.java @@ -0,0 +1,48 @@ +package me.zhengjie.modules.upload.task.model; + +import com.alibaba.fastjson.annotation.JSONField; +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.swagger.annotations.ApiModelProperty; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import javax.persistence.Column; +import java.io.Serializable; +import java.sql.Timestamp; + +@Data +@AllArgsConstructor +@NoArgsConstructor +public class SendRemoteUpdateJsonContent implements Serializable { + + /** + * 上传日志 - 格式为时间戳 + */ + @JSONField(name = "uploadTime") + private Timestamp uploadTime; + + /** + * 上传人/公司 + */ + @JSONField(name = "operation") + private String operation; + + /** + * 上传成功总数 + */ + @JSONField(name = "file_trans_success_count") + private Long fileTransSuccessCount; + + /** + * 上传状态 + */ + @JSONField(name = "uploadTag") + private Integer uploadTag; + + /** + * 文件上传保存路径 + */ + @JSONField(name = "localSavePath") + private String localSavePath; +} diff --git a/eladmin-system/src/main/resources/config/application.yml b/eladmin-system/src/main/resources/config/application.yml index 293c90f..af99a6f 100644 --- a/eladmin-system/src/main/resources/config/application.yml +++ b/eladmin-system/src/main/resources/config/application.yml @@ -59,4 +59,9 @@ remote: address: 'http://47.110.11.213:8000/api/temp/file/download' file-base-path-linux: /home/eladmin/file/temp/ file-base-path-windows: C:\eladmin\file\temp\ - file-base-path-mac: ~/file/eladmin/temp/ \ No newline at end of file + file-base-path-mac: ~/file/eladmin/temp/ +# 发送加密家口需要的一些参数 +inter: + address: https://bd.hzdaba.cn:8085/v3/Accounts/yuyoukeji/BigData/EncryptTel + appid: yuyoukeji + tk: 60da2e99ddb4d56d5ace6ff379fb754a \ No newline at end of file diff --git a/eladmin-system/src/test/java/me/zhengjie/SimpleTest.java b/eladmin-system/src/test/java/me/zhengjie/SimpleTest.java new file mode 100644 index 0000000..7ee5930 --- /dev/null +++ b/eladmin-system/src/test/java/me/zhengjie/SimpleTest.java @@ -0,0 +1,111 @@ +package me.zhengjie; + +import cn.hutool.crypto.SecureUtil; +import cn.hutool.extra.ftp.Ftp; +import cn.hutool.extra.ftp.FtpConfig; +import cn.hutool.extra.ssh.JschUtil; +import cn.hutool.extra.ssh.Sftp; +import com.jcraft.jsch.Session; +import me.zhengjie.utils.DateUtil; +import me.zhengjie.utils.FileUtil; +import me.zhengjie.utils.StringUtils; +import org.junit.Test; + +import java.io.File; +import java.io.IOException; +import java.nio.charset.Charset; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +public class SimpleTest { + + @Test + public void testList2Arr() { + List es = Arrays.asList("1111", "2222", "333"); + + System.out.println(StringUtils.listPrintWithSpecialSplit(es, "|")); + + +/* String s3 = Arrays.toString(es.toArray()); + System.out.println(s3); + + + String s = es.toString(); + + System.out.println(s); + + String s1 = StringUtils.substringBetween(s, "[", "]"); + + System.out.println(s1); + + String s2 = s1.replaceAll(" ", ""); + + System.out.println(s2);*/ + +// System.out.println(StringUtils.strip(es.toString(), "[]")); + + String str = es.toString().replaceAll("(?:\\[|null|]| +)", ""); + System.out.println(str); + + } + + @Test + public void testDateFormate() { + String formateTimestamp = "yyyyMMddHHmmss"; + + System.out.println(new SimpleDateFormat(formateTimestamp).format(new Date())); + + System.out.println(LocalDateTime.now().format(DateTimeFormatter.ofPattern(formateTimestamp))); + + System.out.println(DateUtil.localDateTimeFormat(LocalDateTime.now(), formateTimestamp)); + + String formateTimestamp1 = "yyyy-MM-dd"; + + System.out.println(new SimpleDateFormat(formateTimestamp1).format(new Date())); + } + + @Test + public void testMD5() { + String aa = "21312312312312"; + System.out.println(SecureUtil.md5(aa).toUpperCase()); + } + + + + @Test + public void testFtpTransUpload() { + Session session = JschUtil.getSession("47.110.11.213", 22, "root", "yuyou@ECS2020"); + + Sftp sftp = JschUtil.createSftp(session); + + sftp.put("C:\\Users\\Administrator\\Desktop\\233.txt", "/home"); + + sftp.close(); + } + + @Test + public void testFtpTransDownload() { + Session session = JschUtil.getSession("47.110.11.213", 22, "root", "yuyou@ECS2020"); + + Sftp sftp = JschUtil.createSftp(session); + + sftp.download("/home/233.txt",FileUtil.file("C:\\Users\\Administrator\\Desktop\\233-1.txt")); + + sftp.close(); + } + + @Test + public void testHandleFileName(){ + File file = FileUtil.file("C:\\Users\\Administrator\\Desktop\\233-1.txt"); + + + System.out.println(FileUtil.getName(file)); + + + System.out.println(FileUtil.mainName(file)); + } +} diff --git a/eladmin-system/src/test/java/me/zhengjie/SpringApplicationTest.java b/eladmin-system/src/test/java/me/zhengjie/SpringApplicationTest.java new file mode 100644 index 0000000..9a5b7b5 --- /dev/null +++ b/eladmin-system/src/test/java/me/zhengjie/SpringApplicationTest.java @@ -0,0 +1,21 @@ +package me.zhengjie; + +import me.zhengjie.utils.SecurityUtils; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(SpringRunner.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class SpringApplicationTest { + + + /** + * 获取当前的用户信息 + */ + @Test + public void testGetName(){ + System.out.println(SecurityUtils.getCurrentUsername()); + } +}