Browse Source

重庆热线-附件zip下载及上传功能

dev
Cruyse 5 hours ago
parent
commit
d2dd382109
7 changed files with 269 additions and 21 deletions
  1. +30
    -3
      ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/controller/InBusinessController.java
  2. +109
    -18
      ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/controller/OutBusinessController.java
  3. +130
    -0
      ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/utils/FileZipUtils.java
  4. BIN
      ruoyi-modules/ruoyi-system-dataexchange/src/main/resources/filesIn/0555bede11ac9d64379e9eced17eb91f.jpg
  5. BIN
      ruoyi-modules/ruoyi-system-dataexchange/src/main/resources/filesIn/JT9999992025051710003416_0555bede11ac9d64379e9eced17eb91f.jpg
  6. BIN
      ruoyi-modules/ruoyi-system-dataexchange/src/main/resources/filesOut/0555bede11ac9d64379e9eced17eb999.jpg
  7. BIN
      src/main/resources/filesIn/JT9999992025051710003416_0555bede11ac9d64379e9eced17eb91f.jpg

+ 30
- 3
ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/controller/InBusinessController.java View File

@ -14,6 +14,7 @@ import com.ruoyi.business.domain.*;
import com.ruoyi.business.domain.vo.*; import com.ruoyi.business.domain.vo.*;
import com.ruoyi.business.service.IAdapterService; import com.ruoyi.business.service.IAdapterService;
import com.ruoyi.business.service.IServiceBusinessService; import com.ruoyi.business.service.IServiceBusinessService;
import com.ruoyi.business.utils.FileZipUtils;
import com.ruoyi.common.core.domain.vo.TransportHeader; import com.ruoyi.common.core.domain.vo.TransportHeader;
import com.ruoyi.common.core.domain.vo.TransportRequest; import com.ruoyi.common.core.domain.vo.TransportRequest;
import com.ruoyi.common.core.domain.vo.TransportRequestInfo; import com.ruoyi.common.core.domain.vo.TransportRequestInfo;
@ -193,9 +194,17 @@ public class InBusinessController {
TransportRequest request = buildRequest(ipcType, reqMap, finalToken); TransportRequest request = buildRequest(ipcType, reqMap, finalToken);
logger.info("线程[{}] 请求报文:\n{}", Thread.currentThread().getId(), gson.toJson(request)); logger.info("线程[{}] 请求报文:\n{}", Thread.currentThread().getId(), gson.toJson(request));
String responseJson = postRequest(request, finalUrlSuffix);
TransportResponse response = parseResponse(responseJson);
handleResponse(response, finalUrlSuffix);
if (ipcType.equals("BL1002")) {
Response response = postRequestFile(request, urlSuffix);
FileZipUtils.decryptZip(response);
// response.close(); // 处理完成后手动关闭
} else {
String responseJson = postRequest(request, finalUrlSuffix);
logger.info("返回的response: \n{}", responseJson);
}
// TransportResponse response = parseResponse(responseJson);
// handleResponse(response, finalUrlSuffix);
return success(); return success();
} }
@ -257,6 +266,24 @@ public class InBusinessController {
} }
} }
// 发送HTTP请求
private Response postRequestFile(TransportRequest request, String urlSuffix) throws Exception {
String json = gson.toJson(request);
RequestBody body = RequestBody.create(json, okhttp3.MediaType.get("application/json"));
Request httpRequest = new Request.Builder()
.url(API_ENDPOINT + urlSuffix)
.post(body)
.build();
Response response = httpClient.newCall(httpRequest).execute();
if (!response.isSuccessful()) {
response.close(); // 失败时手动关闭
throw new TransportException("HTTP错误: " + response.code());
}
return response;
}
// 解析响应 // 解析响应
private TransportResponse parseResponse(String json) { private TransportResponse parseResponse(String json) {
return gson.fromJson(json, TransportResponse.class); return gson.fromJson(json, TransportResponse.class);

+ 109
- 18
ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/controller/OutBusinessController.java View File

@ -23,6 +23,7 @@ import com.ruoyi.business.service.IAdapterService;
import com.ruoyi.business.service.IDatabaseService; import com.ruoyi.business.service.IDatabaseService;
import com.ruoyi.business.service.IServiceBusinessService; import com.ruoyi.business.service.IServiceBusinessService;
import com.ruoyi.business.service.IServiceGrantService; import com.ruoyi.business.service.IServiceGrantService;
import com.ruoyi.business.utils.FileZipUtils;
import com.ruoyi.common.auth.entity.OauthClientDetails; import com.ruoyi.common.auth.entity.OauthClientDetails;
import com.ruoyi.common.auth.service.OauthClientDetailsService; import com.ruoyi.common.auth.service.OauthClientDetailsService;
import com.ruoyi.common.core.domain.R; import com.ruoyi.common.core.domain.R;
@ -53,6 +54,7 @@ import org.springframework.web.multipart.MultipartFile;
import javax.servlet.ServletInputStream; import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.sql.DataSource; import javax.sql.DataSource;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -93,7 +95,7 @@ public class OutBusinessController {
private OauthClientDetailsService oauthClientDetailsService; private OauthClientDetailsService oauthClientDetailsService;
@PostMapping @PostMapping
public String outInsert(HttpServletRequest request) throws Exception {
public String outInsert(HttpServletRequest request, HttpServletResponse response) throws Exception {
// if(files != null && files.length > 0 && !Objects.equals(files[0].getOriginalFilename(), "")) { // if(files != null && files.length > 0 && !Objects.equals(files[0].getOriginalFilename(), "")) {
// return outInsert2(request,files, jsonData); // return outInsert2(request,files, jsonData);
// } else { // } else {
@ -130,11 +132,11 @@ public class OutBusinessController {
log.info("==================================token验证成功================================"); log.info("==================================token验证成功================================");
tokenFlag = true; tokenFlag = true;
} else { } else {
log.info("==================================token验证失败2================================");
log.info("==================================token验证失败1================================");
tokenFlag = false; tokenFlag = false;
} }
} else { } else {
log.info("==================================token验证失败3================================");
log.info("==================================token验证失败2================================");
transportRequest.getHeader().setReqType("1"); transportRequest.getHeader().setReqType("1");
transportRequest.getHeader().setCode("9999"); transportRequest.getHeader().setCode("9999");
transportRequest.getHeader().setMessage("token不存在"); transportRequest.getHeader().setMessage("token不存在");
@ -149,6 +151,25 @@ public class OutBusinessController {
String transportResponse = gson.toJson(transportRequest); String transportResponse = gson.toJson(transportRequest);
return transportResponse; return transportResponse;
} }
String ipcType = transportRequest.getHeader().getIpcType();
AjaxResult ajaxResult = AjaxResult.success();
if(ipcType == null || "".equals(ipcType)) {
ajaxResult = AjaxResult.error("ipcType不能为空");
transportRequest.getHeader().setReqType("1");
transportRequest.getHeader().setCode("9999");
transportRequest.getHeader().setMessage(ajaxResult.get("msg").toString());
String transportResponse = gson.toJson(transportRequest);
return transportResponse;
}
if ("GL1001".equals(ipcType)) {
ajaxResult = AjaxResult.success("心跳检测成功");
transportRequest.getHeader().setReqType("1");
transportRequest.getHeader().setCode("9999");
transportRequest.getHeader().setMessage(ajaxResult.get("msg").toString());
String transportResponse = gson.toJson(transportRequest);
return transportResponse;
}
String decryptBodyStr = ""; String decryptBodyStr = "";
if (!org.springframework.util.StringUtils.isEmpty(body)) { if (!org.springframework.util.StringUtils.isEmpty(body)) {
try { try {
@ -158,7 +179,11 @@ public class OutBusinessController {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
AjaxResult ajaxResult = outInsert1(transportRequest,decryptBodyStr);
if ("GL1004".equals(ipcType)) {
outFiles(decryptBodyStr,response);
return "附件获取成功";
}
ajaxResult = outInsert1(transportRequest,decryptBodyStr,response);
if (ajaxResult.isSuccess() || Integer.valueOf(200).equals(ajaxResult.get("code"))) { if (ajaxResult.isSuccess() || Integer.valueOf(200).equals(ajaxResult.get("code"))) {
transportRequest.getHeader().setReqType("1"); transportRequest.getHeader().setReqType("1");
transportRequest.getHeader().setCode("0000"); transportRequest.getHeader().setCode("0000");
@ -173,15 +198,9 @@ public class OutBusinessController {
return transportResponse; return transportResponse;
} }
private AjaxResult outInsert1(TransportRequest transportRequest, String jsonData) throws Exception{
private AjaxResult outInsert1(TransportRequest transportRequest, String jsonData, HttpServletResponse response) throws Exception{
String ipcType = transportRequest.getHeader().getIpcType(); String ipcType = transportRequest.getHeader().getIpcType();
if(ipcType == null || "".equals(ipcType)) {
return AjaxResult.error("ipcType不能为空");
}
if ("GL1001".equals(ipcType)) {
return AjaxResult.success("心跳检测成功");
}
ServiceBusiness serviceBusiness = serviceBusinessService.selectServiceBusinessByOutName(ipcType+"_OUT"); ServiceBusiness serviceBusiness = serviceBusinessService.selectServiceBusinessByOutName(ipcType+"_OUT");
// validGrant(String.valueOf(serviceBusiness.getId())); // validGrant(String.valueOf(serviceBusiness.getId()));
if(!BusinessServiceEnum.insert.getCode().equals(serviceBusiness.getType())) { if(!BusinessServiceEnum.insert.getCode().equals(serviceBusiness.getType())) {
@ -210,8 +229,32 @@ public class OutBusinessController {
final String finalReqBody = reqBody; final String finalReqBody = reqBody;
TransportRequestInfo transportRequestInfo = JSONObject.parseObject(jsonData, TransportRequestInfo.class); TransportRequestInfo transportRequestInfo = JSONObject.parseObject(jsonData, TransportRequestInfo.class);
Map<String,Object> transportMap = (Map<String, Object>) transportRequestInfo.getReqInfo(); Map<String,Object> transportMap = (Map<String, Object>) transportRequestInfo.getReqInfo();
JSONArray jsonArray = (JSONArray.parseArray(String.valueOf(transportMap.get(finalReqBody))));
log.info(jsonArray.toString());
//JSONArray jsonArray = (JSONArray.parseArray(String.valueOf(transportMap.get(finalReqBody))));
//log.info(jsonArray.toString());
// 增加JSON类型判断逻辑
Object data = transportMap.get(finalReqBody);
String jsonStr = String.valueOf(data);
JSONArray jsonArray;
if (StringUtils.isNotEmpty(jsonStr)) {
if (jsonStr.trim().startsWith("[")) {
jsonArray = JSONArray.parseArray(jsonStr);
} else if (jsonStr.trim().startsWith("{")) {
// 如果字段要求数组但收到对象可以按需处理
// 1. 返回错误return AjaxResult.error(finalReqBody + "字段应为数组格式");
// 2. 包装成数组
jsonArray = new JSONArray();
jsonArray.add(JSONObject.parseObject(jsonStr));
} else {
return AjaxResult.error(finalReqBody + "字段格式异常,应为JSON数组或对象");
}
} else {
return AjaxResult.error(finalReqBody + "字段不能为空");
}
log.info("插入的jsonArray.toString数组:"+jsonArray.toString());
int batchSize = 50; int batchSize = 50;
if (jsonArray.size() > batchSize) { if (jsonArray.size() > batchSize) {
return AjaxResult.error("超过50条数据"); return AjaxResult.error("超过50条数据");
@ -355,6 +398,51 @@ public class OutBusinessController {
return AjaxResult.success("插入成功"); return AjaxResult.success("插入成功");
} }
private void outFiles(String jsonData, HttpServletResponse response) throws Exception{
String finalReqBody = "recordInfo";
// 新增final副本用于lambda
TransportRequestInfo transportRequestInfo = JSONObject.parseObject(jsonData, TransportRequestInfo.class);
Map<String,Object> transportMap = (Map<String, Object>) transportRequestInfo.getReqInfo();
Object data = transportMap.get(finalReqBody);
String jsonStr = String.valueOf(data);
JSONArray jsonArray = new JSONArray();
if (StringUtils.isNotEmpty(jsonStr)) {
if (jsonStr.trim().startsWith("[")) {
jsonArray = JSONArray.parseArray(jsonStr);
} else if (jsonStr.trim().startsWith("{")) {
// 如果字段要求数组但收到对象可以按需处理
// 1. 返回错误return AjaxResult.error(finalReqBody + "字段应为数组格式");
// 2. 包装成数组
jsonArray = new JSONArray();
jsonArray.add(JSONObject.parseObject(jsonStr));
}
}
log.info("jsonArray.toString数组:"+jsonArray.toString());
Map<String,String> fileInfo = new HashMap<>();
// 循环处理JSONArray中的每个JSONObject
for (int i = 0; i < jsonArray.size(); i++) {
final int idx = i; // 创建final副本解决lambda表达式变量捕获问题
JSONObject jsonObject = jsonArray.getJSONObject(idx);
for (String key : jsonObject.keySet()) {
Object value = jsonObject.get(key);
if (key.contains("Id")) {
fileInfo.put("Id", String.valueOf(value));
}
if (key.contains("Name")) {
fileInfo.put("Name", String.valueOf(value));
}
if (key.contains("Type")) {
fileInfo.put("Type", String.valueOf(value));
}
}
}
FileZipUtils.getEncryptZip(response,fileInfo);
}
/** /**
* 接口权限 * 接口权限
* @param businessId 业务id * @param businessId 业务id
@ -719,12 +807,15 @@ public class OutBusinessController {
// 设置参数 // 设置参数
for (String key : json.keySet()) { for (String key : json.keySet()) {
if (resFieldSet.contains(FebsUtil.camelToUnderscore(key))) { if (resFieldSet.contains(FebsUtil.camelToUnderscore(key))) {
// 检查是否是 JsonArray类型比如qxhydsxx 字段确保它是一个有效的 JSON 字符串
if (json.get(key) instanceof JSONArray) {
// JSON 对象转换为字符串
ps.setString(index++, json.getJSONArray(key).toString());
Object value = json.get(key);
if (value instanceof JSONArray) {
ps.setString(index++, ((JSONArray) value).toJSONString());
} else if (value instanceof JSONObject) {
ps.setString(index++, ((JSONObject) value).toJSONString());
} else if (value != null) {
ps.setString(index++, value.toString());
} else { } else {
ps.setObject(index++, json.get(key));
ps.setNull(index++, Types.VARCHAR);
} }
} }
} }

+ 130
- 0
ruoyi-modules/ruoyi-system-dataexchange/src/main/java/com/ruoyi/business/utils/FileZipUtils.java View File

@ -0,0 +1,130 @@
package com.ruoyi.business.utils;
import net.lingala.zip4j.io.inputstream.ZipInputStream;
import net.lingala.zip4j.io.outputstream.ZipOutputStream;
import net.lingala.zip4j.model.LocalFileHeader;
import net.lingala.zip4j.model.ZipParameters;
import net.lingala.zip4j.model.enums.CompressionLevel;
import net.lingala.zip4j.model.enums.CompressionMethod;
import net.lingala.zip4j.model.enums.EncryptionMethod;
import okhttp3.Response;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
public class FileZipUtils {
public static void decryptZip(Response response) throws Exception {
Path storageDir = Paths.get(
System.getProperty("user.dir"), // 获取项目根目录
"ruoyi-modules/ruoyi-system-dataexchange/src/main/resources/filesIn" // 指定存储目录
).toAbsolutePath();
// 确保目录存在
Files.createDirectories(storageDir);
// 修改为项目根目录下的存储路径
System.out.println("Final storage path: " + storageDir.toAbsolutePath());
// System.out.println("响应体body: " + response.body().string());
// 确保目录存在
Files.createDirectories(storageDir);
try (InputStream responseInputStream = response.body().byteStream()) {
// 2. 设置ZIP密码
String password = "QLdQIASYMlT9SUUg";
List<String> extractedContents = new ArrayList<>();
try (ZipInputStream zipInputStream = new ZipInputStream(responseInputStream, password.toCharArray())) {
LocalFileHeader fileHeader;
byte[] buffer = new byte[8192]; // 8KB 缓冲区
// 遍历 ZIP 中的每个文件
while ((fileHeader = zipInputStream.getNextEntry()) != null) {
String fileName = fileHeader.getFileName().split("_")[1];
Path outputPath = storageDir.resolve(fileName);
// 确保父目录存在
Files.createDirectories(outputPath.getParent());
try (OutputStream outputStream = Files.newOutputStream(outputPath)) {
int bytesRead;
while ((bytesRead = zipInputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
}
}
}
}
}
public static void getEncryptZip(HttpServletResponse response, Map<String, String> fileInfo) throws IOException {
// 1. 定义要下载的图片URL列表
List<String> imageUrls = new ArrayList<>();
Path storageDir = Paths.get(
System.getProperty("user.dir"), // 获取项目根目录
"ruoyi-modules\\ruoyi-system-dataexchange\\src\\main\\resources\\filesOut" // 改用Windows路径分隔符
).toAbsolutePath();
imageUrls.add(storageDir.resolve(fileInfo.get("Name")).toString());
// imageUrls.add(storageDir.resolve("1512b987-6954-4533-8154-e8b8bcce5a6e.png").toString());
// 2. 设置ZIP密码
String password = "8iot1blDJgNK36Do";
setResHeader(response, "MaterialFile-"+fileInfo.get("Id")+".zip");
// 3. 创建ZIP输出流直接写入HTTP响应流
try (ServletOutputStream outputStream = response.getOutputStream()) {
try (ZipOutputStream zipOut = new ZipOutputStream(outputStream, password.toCharArray())) {
for (String imageUrl : imageUrls) {
try (FileInputStream fileInputStream = new FileInputStream(new File(imageUrl))) {
addFileToZip(zipOut, fileInputStream, fileInfo.get("Id")+"_"+imageUrl.substring(imageUrl.lastIndexOf("\\") + 1));
}
}
}
}
}
/**
* @Description: 设置响应头
* @data:[response,zipFileName 文件名没有后缀]
* @Author: J
* @Date: 2025-03-26 13:57:13
*/
public static void setResHeader(HttpServletResponse response, String zipFileName) {
try {
response.setContentType("application/zip");
response.setHeader("Content-Disposition", "attachment; filename=" + URLEncoder.encode(zipFileName + ".zip", "UTF-8"));
} catch (UnsupportedEncodingException e) {
throw new RuntimeException(e);
}
}
/**
* @Description: 将图片下载并打包成ZIP文件写入输出流
* @data:[zipOut zip输出流, imageInputStream 单个文件流, fileName 单个文件名称带后缀]
* @Author: J
* @Date: 2025-03-26 13:55:10
*/
public static void addFileToZip(ZipOutputStream zipOut, InputStream imageInputStream, String fileName) throws IOException {
ZipParameters zipParams = new ZipParameters();
zipParams.setCompressionMethod(CompressionMethod.DEFLATE); // 使用 DEFLATE 算法
zipParams.setCompressionLevel(CompressionLevel.HIGHER); // 设置压缩级别
zipParams.setFileNameInZip(fileName);
zipParams.setEncryptFiles(true);
zipParams.setEncryptionMethod(EncryptionMethod.AES);
// 3. 开始写入ZIP条目
zipOut.putNextEntry(zipParams);
// 4. 下载图片并流式写入ZIP
try (InputStream imageStream = imageInputStream) {
int bytesRead;
byte[] buffer = new byte[8192]; // 8KB缓冲区
while ((bytesRead = imageStream.read(buffer)) != -1) {
zipOut.write(buffer, 0, bytesRead);
}
}
// 5. 关闭当前条目
zipOut.closeEntry();
}
}

BIN
ruoyi-modules/ruoyi-system-dataexchange/src/main/resources/filesIn/0555bede11ac9d64379e9eced17eb91f.jpg View File

Before After
Width: 1279  |  Height: 1706  |  Size: 92 KiB

BIN
ruoyi-modules/ruoyi-system-dataexchange/src/main/resources/filesIn/JT9999992025051710003416_0555bede11ac9d64379e9eced17eb91f.jpg View File

Before After
Width: 1279  |  Height: 1706  |  Size: 92 KiB

BIN
ruoyi-modules/ruoyi-system-dataexchange/src/main/resources/filesOut/0555bede11ac9d64379e9eced17eb999.jpg View File

Before After
Width: 411  |  Height: 402  |  Size: 135 KiB

BIN
src/main/resources/filesIn/JT9999992025051710003416_0555bede11ac9d64379e9eced17eb91f.jpg View File

Before After
Width: 1279  |  Height: 1706  |  Size: 92 KiB

Loading…
Cancel
Save