> 技术文档 > JAVA实现从SFTP 服务器中获取文件信息

JAVA实现从SFTP 服务器中获取文件信息

最近在项目中遇见一个问题,甲方再给数据的时候,是存在SFTP服务器上面的,所以有了这么一种小众的实现

下面展示文件的格式:

内部相当于txt1,txt2,txt3,txt4  四张表的数据

基本的文件相关信息

基本配置信息

依赖库:

  com.jcraft jsch 0.1.55    net.lingala.zip4j zip4j 2.10.0 

废话不说了,上代码:基本实现了自动化落库存储

 public void getDownload(String targetDate) { // 按照时间对文件夹进行拼接 String folder = remoteDir + targetDate; JSch jsch = new JSch(); Session session = null; ChannelSftp channelSftp = null; File tempZipFile = null; // 临时文件夹 try { // 创建SSH会话 session = jsch.getSession(username, url, Integer.parseInt(port)); session.setPassword(password); // 配置SSH会话 Properties config = new Properties(); config.put(\"StrictHostKeyChecking\", \"no\"); session.setConfig(config); // 连接SSH会话 session.connect(); log.info(\"SSH会话已连接\"); // 打开SFTP通道 channelSftp = (ChannelSftp) session.openChannel(\"sftp\"); channelSftp.connect(); log.info(\"SFTP通道已连接\"); // 获取远程目录下的文件列表 List files = channelSftp.ls(folder); // 构造目标文件名 String targetFileName = folder + \"/\" + targetDate + \".zip\"; // 遍历文件列表 for (ChannelSftp.LsEntry entry : files) { String remoteFile = folder + \"/\" + entry.getFilename(); String fileNameFromTarget = targetFileName.substring(targetFileName.lastIndexOf(\"/\") + 1); // 获取目标文件的文件名部分 // 如果文件名与目标日期匹配,处理该ZIP文件 if (!entry.getAttrs().isDir() && entry.getFilename().equals(fileNameFromTarget)) {  log.info(\"正在处理ZIP文件: {}\", remoteFile);  // 下载ZIP文件到临时文件夹  tempZipFile = downloadFileToTempFile(channelSftp, remoteFile);  // 解压ZIP文件  boolean isMatched = unzipFileWithPassword(tempZipFile, zipPassword);  if (!isMatched) { log.info(\"当前ZIP文件没有匹配的JSON文件,跳过该文件\");  }  break; } } log.info(\"文件处理完成!\"); } catch (Exception e) { log.error(\"SFTP下载过程中发生错误\", e); } finally { // 关闭SFTP通道和会话 if (channelSftp != null) { channelSftp.disconnect(); } if (session != null) { session.disconnect(); } // 当前方法结束后删除临时文件夹 if (tempZipFile != null && tempZipFile.exists()) { boolean isDeleted = tempZipFile.delete(); if (isDeleted) {  log.info(\"临时ZIP文件已删除: {}\", tempZipFile.getAbsolutePath()); } else {  log.warn(\"临时ZIP文件删除失败(可能被占用): {}\", tempZipFile.getAbsolutePath()); } } } } /** * 服务器存储地址 * * @param channelSftp * @param remoteFile * @return */ public File downloadFileToServerFile(ChannelSftp channelSftp, String remoteFile) { File serverZipFile = null; try { // 设置服务器上的文件存储路径 String serverDirPath = tmp; // 你可以替换为你希望存储的服务器路径 File serverDir = new File(serverDirPath); // 如果目录不存在,则创建 if (!serverDir.exists()) { serverDir.mkdirs(); } // 创建文件名并指向服务器路径 serverZipFile = new File(serverDir, \"downloaded_\" + System.currentTimeMillis() + \".zip\"); // 下载文件到指定的服务器路径 try (OutputStream outputStream = Files.newOutputStream(serverZipFile.toPath())) { channelSftp.get(remoteFile, outputStream); log.info(\"文件 {} 已下载到服务器路径: {}\", remoteFile, serverZipFile.getAbsolutePath()); } } catch (Exception e) { log.error(\"下载文件 {} 到服务器路径时出错\", remoteFile, e); } return serverZipFile; } /** * 解压带密码的ZIP文件(临时文件版) * 返回是否有匹配的文件 */ public boolean unzipFileWithPassword(File zipFile, String password) { boolean isMatched = false; try { ZipFile zip = new ZipFile(zipFile); // 如果ZIP文件加密,设置密码 if (zip.isEncrypted()) { zip.setPassword(password.toCharArray()); } List fileHeaders = zip.getFileHeaders(); for (FileHeader fileHeader : fileHeaders) { // 匹配文件名 Pattern pattern = Pattern.compile(\"nj_yuhuatai_result_txt[1-4]_(\\\\d{8})\\\\.json\"); Matcher matcher = pattern.matcher(fileHeader.getFileName()); if (matcher.matches()) {  isMatched = true;  log.info(\"匹配到文件: {}\", fileHeader.getFileName());  // 直接读取文件内容,不再创建临时文件  try (InputStream inputStream = zip.getInputStream(fileHeader)) { // 读取解压后的文件内容 ByteArrayOutputStream jsonFileOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = inputStream.read(buffer)) != -1) { if (bytesRead > 0) { jsonFileOutputStream.write(buffer, 0, bytesRead); } } // 使用UTF-8字符集将字节流转换为字符串 String respData = jsonFileOutputStream.toString(StandardCharsets.UTF_8.name()); if (respData.isEmpty()) { log.error(\"解压后的内容为空: {}\", fileHeader.getFileName()); } else { String fileName = fileHeader.getFileName(); String fileType = getFileType(fileName); String date = getFileDate(fileName); processJsonData(respData, fileType, date); }  } catch (IOException e) { log.error(\"读取文件失败: {}\", fileHeader.getFileName(), e); continue; // 跳过该文件  } } } log.info(\"ZIP文件已解压\"); } catch (IOException e) { log.error(\"解压文件出错\", e); } return isMatched; } /** * 从文件名中提取文件类型 */ public String getFileType(String fileName) { Pattern pattern = Pattern.compile(\"nj_yuhuatai_result_(txt\\\\d)_\"); Matcher matcher = pattern.matcher(fileName); if (matcher.find()) { return matcher.group(1); // 如txt1, txt2 } return \"unknown\"; } /** * 从文件名中提取日期 */ public String getFileDate(String fileName) { Pattern pattern = Pattern.compile(\"\\\\d{8}.json$\"); Matcher matcher = pattern.matcher(fileName); if (matcher.find()) { return matcher.group().replace(\".json\", \"\"); } return \"unknown\"; } /** * 处理JSON数据 */ public void processJsonData(String jsonData, String fileType, String date) { // 在此处理JSON数据,可能是存储到数据库等 switch (fileType) { case \"txt1\": getInsertTxt1(jsonData); break; case \"txt2\": getInsertTxt2(jsonData); break; case \"txt3\": getInsertTxt3(jsonData); break; default: getInsertTxt4(jsonData); break; } log.info(\"正在处理JSON数据,文件类型: {},日期: {},数据:{}\", fileType, date, jsonData); } /** * 消费数据获取 * * @param jsonData */ public void getInsertTxt1(String jsonData) { JSONObject jsonObject = JSON.parseObject(jsonData); String dt = jsonObject.get(\"dt\").toString(); String transDistrict = jsonObject.get(\"trans_district\").toString(); String amt = jsonObject.get(\"amt\").toString(); String freq = jsonObject.get(\"freq\").toString(); String card = jsonObject.get(\"card\").toString(); ConsumptionDataTxtOne one = new ConsumptionDataTxtOne(); one.setId(ToolCollectionUtil.UUID()); one.setDt(dt); one.setTransDistrict(transDistrict); one.setAmt(amt); one.setFreq(freq); one.setCard(card); zhwlAreaTableMapper.getInsertTxt1Save(one); } /** * 游玩类型数据获取 ,将数据合为一条 * * @param jsonData */ public void getInsertTxt2(String jsonData) { // 手动包装JSON数据为数组 String jsonArrayData = \"[\" + jsonData + \"]\"; // 添加方括号包裹数据 JSONArray jsonArray = JSONArray.parseArray(jsonArrayData); // 遍历JSONArray中的每一条数据 for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); String id = ToolCollectionUtil.UUID(); String dt = jsonObject.getString(\"dt\"); String transDistrict = jsonObject.getString(\"trans_district\"); String cate = jsonObject.getString(\"cate\"); String amtPct = jsonObject.getString(\"amt_pct\"); String freqPct = jsonObject.getString(\"freq_pct\"); String cardPct = jsonObject.getString(\"card_pct\"); ConsumptionDataTxtTwo two = new ConsumptionDataTxtTwo(); two.setId(id); two.setDt(dt); two.setTransDistrict(transDistrict); two.setCate(cate); two.setAmtPct(amtPct); two.setFreqPct(freqPct); two.setCardPct(cardPct); two.setCardPct(cardPct); // 查询如果是空的再插入 ConsumptionDataTxtTwo selectTxt2Save = zhwlAreaTableMapper.getSelectTxt2Save(dt, cate); if (selectTxt2Save == null) { zhwlAreaTableMapper.getInsertTxt2Save(two); } } } /** * 年龄阶段获取 * * @param jsonData */ public void getInsertTxt3(String jsonData) { String jsonArrayData = \"[\" + jsonData + \"]\"; // 添加方括号包裹数据 JSONArray jsonArray = JSONArray.parseArray(jsonArrayData); // 遍历JSONArray中的每一条数据 for (int i = 0; i < jsonArray.size(); i++) { JSONObject jsonObject = jsonArray.getJSONObject(i); String id = ToolCollectionUtil.UUID(); String dt = jsonObject.getString(\"dt\"); String label = jsonObject.getString(\"label\"); String amtPct = jsonObject.getString(\"amt_pct\"); String freqPct = jsonObject.getString(\"freq_pct\"); String cardPct = jsonObject.getString(\"card_pct\"); ConsumptionDataTxtThree three = new ConsumptionDataTxtThree(); three.setId(id); three.setDt(dt); three.setLabel(label); three.setAmtPct(amtPct); three.setFreqPct(freqPct); three.setCardPct(cardPct); // 查询如果是空的再插入 ConsumptionDataTxtThree selectTxt3Save = zhwlAreaTableMapper.getSelectTxt3Save(dt, label); if (selectTxt3Save == null) { zhwlAreaTableMapper.getInsertTxt3Save(three); } } } /** * 区域类型获取 * * @param jsonData */ public void getInsertTxt4(String jsonData) { String jsonArrayData = \"[\" + jsonData + \"]\"; // 添加方括号包裹数据 JSONArray jsonArray = JSONArray.parseArray(jsonArrayData); List dataList = new ArrayList(); // 遍历JSONArray中的每一条数据 for (int i = 0; i  { double max1 = Math.max(Math.max(Double.parseDouble(o1.getAmtPct()), Double.parseDouble(o1.getFreqPct())), Double.parseDouble(o1.getCardPct())); double max2 = Math.max(Math.max(Double.parseDouble(o2.getAmtPct()), Double.parseDouble(o2.getFreqPct())), Double.parseDouble(o2.getCardPct())); return Double.compare(max2, max1); }); // 取前6条有效数据(已过滤空perm_city的情况) List top6 = dataList.subList(0, Math.min(6, dataList.size())); // 插入数据库(已存在则跳过) for (ConsumptionDataTxtFour four : top6) { ConsumptionDataTxtFour selectTxt4Save = zhwlAreaTableMapper.getSelectTxt4Save(four.getDt(), four.getPermCity()); if (selectTxt4Save == null) { zhwlAreaTableMapper.getInsertTxt4Save(four); } } }

包装材料种类