This commit is contained in:
oneao committed 2026-03-28 17:22:49 +08:00
1 parent ce466130c0
commit 9c026f00ad
36 files changed
+2230 -1036

No files matched your search

+11
View File
@@ -83,6 +83,17 @@
<artifactId>oshi-core</artifactId>
<version>6.10.0</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
@@ -7,12 +7,14 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.annotation.EnableScheduling;
@SpringBootApplication(exclude = {
DataSourceAutoConfiguration.class,
DruidDataSourceAutoConfigure.class ,
})
@EnableAsync
@EnableAsync // 异步
@EnableScheduling // 定时任务
public class ApiApplication {
public static void main(String[] args){
// 初始化雪花id
@@ -0,0 +1,46 @@
package cn.g3soft.config;
import cn.g3soft.utils.PathUtils;
import lombok.Data;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Data
@Component
@ConfigurationProperties(prefix = "file")
public class FileConfig {
private String baseDir;
private String tempDir;
private String containerDir;
private String staticPath;
private String serverUrl;
public String getTempPath() {
return PathUtils.joinFilePath(baseDir, tempDir);
}
public String getContainerPath(){
return PathUtils.joinFilePath(baseDir,containerDir);
}
public String buildTempFilePath(String fileName) {
return PathUtils.joinFilePath(baseDir, tempDir, fileName);
}
public String getStaticUrlPrefix() {
return PathUtils.joinUrl(serverUrl, staticPath);
}
public String buildTempUrl(String fileName) {
return PathUtils.joinUrl(serverUrl, staticPath, tempDir, fileName);
}
public String buildFileUrl(String relativePath) {
return PathUtils.joinUrl(serverUrl, staticPath, relativePath);
}
}
@@ -3,28 +3,38 @@ package cn.g3soft.config;
import cn.g3soft.interceptor.AuthInterceptor;
import cn.g3soft.interceptor.DataSourceInterceptor;
import cn.g3soft.interceptor.RequestWrapperFilter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
import javax.annotation.Resource;
@Configuration
@Slf4j
public class WebMvcConfig implements WebMvcConfigurer {
@Resource
private FileConfig fileConfig;
@Override
public void addInterceptors(InterceptorRegistry registry) {
registry.addInterceptor(new AuthInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(
"/auth/login",
"/error"
"/error",
"/static/**"
);
registry.addInterceptor(new DataSourceInterceptor())
.addPathPatterns("/**")
.excludePathPatterns(
"/auth/login",
"/error"
"/error",
"/static/**"
);
}
@@ -33,7 +43,13 @@ public class WebMvcConfig implements WebMvcConfigurer {
FilterRegistrationBean<RequestWrapperFilter> registration = new FilterRegistrationBean<>();
registration.setFilter(new RequestWrapperFilter());
registration.addUrlPatterns("/*");
registration.setOrder(1); // 一定要靠前
registration.setOrder(1);
return registration;
}
@Override
public void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler(fileConfig.getStaticPath() + "/**")
.addResourceLocations("file:" + fileConfig.getUploadDir() + "/");
}
}
@@ -7,8 +7,10 @@ import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@@ -18,123 +20,26 @@ import java.util.Map;
public class FileController {
@Resource
private DbUtils dbUtils;
@Resource
private FileUploadUtils fileUploadUtils;
@PostMapping("/getAliyunKey")
public Result<Map<String,Object>> getAliyunKey(@RequestBody Map<String, Object> params) {
ValidationUtils.checkRequiredFields(params, "bucketName");
String bucketName = (String) params.get("bucketName");
String orgId = UserContext.get().getOrgId();
String requestUrl = "http://g3oss.g3soft.cn:8082/upload?orgid=" + orgId + "&bucket=" + bucketName;
String reqResult = HttpUtils.sendGet(requestUrl);
Map<String, Object> objectMap = JsonUtils.toMap(reqResult);
return Result.ok(objectMap);
}
@PostMapping("/insert")
@Transactional(rollbackFor = Exception.class)
public Result<Long> insertFile(@RequestBody Map<String,Object> params) {
ValidationUtils.checkRequiredFields(params, "father", "mx_xh", "mx_filename", "mx_filesize", "mx_mapfilename", "mx_moduleid");
String userId = UserContext.get().getUserId();
long nextId = UniqueId.nextId();
params.put("subid", nextId);
params.put("mx_inputuser_id",userId);
params.put("mx_inputdatetime", TimeUtils.getDateTime());
dbUtils.insert("bf_file","subid",params);
return Result.ok(nextId);
}
@PostMapping("/delete")
@Transactional(rollbackFor = Exception.class)
public Result<Void> deleteFile(@RequestBody Map<String, Object> params) {
ValidationUtils.checkRequiredFields(params, "subid", "tableName", "bucketName");
String tableName = params.get("tableName").toString();
String bucketName = params.get("bucketName").toString();
String id = params.get("subid").toString();
// 查询数据
List<Map<String, Object>> maps = dbUtils.loadData("SELECT * FROM " + tableName + " WHERE subid = ?", id);
// 如果没有数据,直接返回删除成功
if (ObjectUtils.isEmpty(maps)) {
return Result.ok("删除成功");
}
String mxMapfilename = maps.get(0).get("mx_mapfilename").toString();
String orgId = UserContext.get().getOrgId();
int index = mxMapfilename.indexOf(orgId + "/");
// 如果没找到,就转换orgId为大写
if (index < 0) {
orgId = orgId.toUpperCase();
index = mxMapfilename.indexOf(orgId + "/");
}
String objectName = mxMapfilename.substring(index);
// 删除记录
Map<String, Object> deleteParams = new HashMap<>();
deleteParams.put("subid", id);
int deleteCount = dbUtils.delete(tableName, deleteParams);
// 如果删除成功,发送删除请求
if (deleteCount > 0) {
if(StringUtils.isBlank(objectName)){
return Result.fail("删除失败,文件格式有误");
}
String requestUrl = String.format("http://g3oss.g3soft.cn:8082/delete?bucketName=%s&objectName=%s", bucketName, objectName);
try {
HttpUtils.sendGet(requestUrl);
} catch (Exception e) {
throw new RuntimeException("删除文件失败",e);
}
}
return Result.ok();
}
@PostMapping("/deleteAliyunFile")
@Transactional(rollbackFor = Exception.class)
public Result<Void> deleteAliyunFile(@RequestBody Map<String, Object> params) {
ValidationUtils.checkRequiredFields(params, "bucketName", "mx_mapfilename");
String bucketName = params.get("bucketName").toString();
String mxMapfilename = params.get("mx_mapfilename").toString();
String orgId = UserContext.get().getOrgId();
int index = mxMapfilename.indexOf(orgId + "/");
// 如果没找到,就转换orgId为大写
if (index < 0) {
orgId = orgId.toUpperCase();
index = mxMapfilename.indexOf(orgId + "/");
}
String objectName = mxMapfilename.substring(index);
if(StringUtils.isBlank(objectName)){
return Result.fail("删除失败,文件格式有误");
}
// 发送删除请求
String requestUrl = String.format("http://g3oss.g3soft.cn:8082/delete?bucketName=%s&objectName=%s", bucketName, objectName);
System.out.println(requestUrl);
/**
* 上传临时文件接口
*/
@PostMapping("/uploadTemp")
public Result<Map<String, String>> uploadTemp(@RequestParam("file") MultipartFile file,
@RequestParam(value = "fileName") String fileName) {
Map<String, String> response = new HashMap<>();
try {
HttpUtils.sendGet(requestUrl);
} catch (Exception e) {
throw new RuntimeException("删除文件失败",e);
}
// 调用工具类上传临时文件,返回临时 URL
String tempUrl = fileUploadUtils.uploadTemp(file,fileName);
return Result.ok();
// 返回临时文件 URL
response.put("tempUrl", tempUrl);
return Result.ok(response);
} catch (IOException e) {
return Result.fail("文件上传失败:" + e.getMessage());
}
}
}
@@ -33,7 +33,7 @@ public class OcrController {
reqPayload.put("visualize", false);
try {
String response = HttpUtils.sendPostJson(requestUrl, reqPayload);
String response = HttpUtils.postJson(requestUrl, reqPayload);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response);
@@ -0,0 +1,140 @@
package cn.g3soft.controller;
import cn.g3soft.context.UserContext;
import cn.g3soft.utils.*;
import cn.g3soft.utils.uniqueId.idgen.UniqueId;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@RestController
@RequestMapping("/file")
public class OssController {
@Resource
private DbUtils dbUtils;
@PostMapping("/getAliyunKey")
public Result<Map<String,Object>> getAliyunKey(@RequestBody Map<String, Object> params) throws Exception {
ValidationUtils.checkRequiredFields(params, "bucketName");
String bucketName = (String) params.get("bucketName");
String orgId = UserContext.get().getOrgId();
String requestUrl = "http://g3oss.g3soft.cn:8082/upload?orgid=" + orgId + "&bucket=" + bucketName;
String reqResult = HttpUtils.get(requestUrl);
Map<String, Object> objectMap = JsonUtils.toMap(reqResult);
return Result.ok(objectMap);
}
@PostMapping("/insert")
@Transactional(rollbackFor = Exception.class)
public Result<Long> insertFile(@RequestBody Map<String,Object> params) {
ValidationUtils.checkRequiredFields(params, "father", "mx_xh", "mx_filename", "mx_filesize", "mx_mapfilename", "mx_moduleid");
String userId = UserContext.get().getUserId();
long nextId = UniqueId.nextId();
params.put("subid", nextId);
params.put("mx_inputuser_id",userId);
params.put("mx_inputdatetime", TimeUtils.getDateTime());
dbUtils.insert("bf_file","subid",params);
return Result.ok(nextId);
}
@PostMapping("/delete")
@Transactional(rollbackFor = Exception.class)
public Result<Void> deleteFile(@RequestBody Map<String, Object> params) {
ValidationUtils.checkRequiredFields(params, "subid", "tableName", "bucketName");
String tableName = params.get("tableName").toString();
String bucketName = params.get("bucketName").toString();
String id = params.get("subid").toString();
// 查询数据
List<Map<String, Object>> maps = dbUtils.loadData("SELECT * FROM " + tableName + " WHERE subid = ?", id);
// 如果没有数据,直接返回删除成功
if (ObjectUtils.isEmpty(maps)) {
return Result.ok("删除成功");
}
String mxMapfilename = maps.get(0).get("mx_mapfilename").toString();
String orgId = UserContext.get().getOrgId();
int index = mxMapfilename.indexOf(orgId + "/");
// 如果没找到,就转换orgId为大写
if (index < 0) {
orgId = orgId.toUpperCase();
index = mxMapfilename.indexOf(orgId + "/");
}
String objectName = mxMapfilename.substring(index);
// 删除记录
Map<String, Object> deleteParams = new HashMap<>();
deleteParams.put("subid", id);
int deleteCount = dbUtils.delete(tableName, deleteParams);
// 如果删除成功,发送删除请求
if (deleteCount > 0) {
if(StringUtils.isBlank(objectName)){
return Result.fail("删除失败,文件格式有误");
}
String requestUrl = String.format("http://g3oss.g3soft.cn:8082/delete?bucketName=%s&objectName=%s", bucketName, objectName);
try {
HttpUtils.get(requestUrl);
} catch (Exception e) {
throw new RuntimeException("删除文件失败",e);
}
}
return Result.ok();
}
@PostMapping("/deleteAliyunFile")
@Transactional(rollbackFor = Exception.class)
public Result<Void> deleteAliyunFile(@RequestBody Map<String, Object> params) {
ValidationUtils.checkRequiredFields(params, "bucketName", "mx_mapfilename");
String bucketName = params.get("bucketName").toString();
String mxMapfilename = params.get("mx_mapfilename").toString();
String orgId = UserContext.get().getOrgId();
int index = mxMapfilename.indexOf(orgId + "/");
// 如果没找到,就转换orgId为大写
if (index < 0) {
orgId = orgId.toUpperCase();
index = mxMapfilename.indexOf(orgId + "/");
}
String objectName = mxMapfilename.substring(index);
if(StringUtils.isBlank(objectName)){
return Result.fail("删除失败,文件格式有误");
}
// 发送删除请求
String requestUrl = String.format("http://g3oss.g3soft.cn:8082/delete?bucketName=%s&objectName=%s", bucketName, objectName);
System.out.println(requestUrl);
try {
HttpUtils.get(requestUrl);
} catch (Exception e) {
throw new RuntimeException("删除文件失败",e);
}
return Result.ok();
}
}
@@ -0,0 +1,44 @@
package cn.g3soft.schedule;
import cn.g3soft.config.FileConfig;
import cn.g3soft.utils.PathUtils;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.io.File;
@Component
public class TempFIleSchedule {
@Resource
private FileConfig fileConfig;
/**
* 定时清理临时文件(临时文件超过1天后清理)
*/
@Scheduled(cron = "0 0 3 * * ?") // 每天3点清理
public void cleanTempFiles() {
File tempDir = new File(PathUtils.joinFilePath(fileConfig.getTempPath()));
if (tempDir.exists()) {
File[] files = tempDir.listFiles();
if (files != null) {
for (File file : files) {
if (isFileExpired(file)) {
file.delete();
}
}
}
}
}
/**
* 判断文件是否过期(假设超过1天的文件删除)
* @param file 文件
* @return 是否过期
*/
private boolean isFileExpired(File file) {
long lastModified = file.lastModified();
long now = System.currentTimeMillis();
return now - lastModified > 86400000L; // 1天的毫秒数
}
}
@@ -0,0 +1,99 @@
package cn.g3soft.utils;
import cn.g3soft.config.FileConfig;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
/**
* 通用文件上传工具类
* 规则:
* - 文件名保持原始或指定
* - 同一天同箱号重复 -> 自动生成 _1/_2/... 文件夹
* - 使用 FileUtils 拼接路径
*/
@Component
public class FileContainerUtils {
@Resource
private FileConfig fileConfig;
/**
* 单文件上传
*/
public String upload(MultipartFile file, String containerNo, String fileName) throws IOException {
if (file == null || file.isEmpty()) {
throw new RuntimeException("文件不能为空");
}
// 1. 日期路径 yyyy/MM/dd
String datePath = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy/MM/dd"));
// 2. 基础目录:上传目录 + 日期
String basePath = PathUtils.joinFilePath(fileConfig.getContainerPath(), datePath);
// 3. 计算最终目录(箱号 + 重复批次)
File finalDir = resolveContainerDir(basePath, containerNo);
if (!finalDir.exists()) {
finalDir.mkdirs();
}
// 4. 最终文件
File dest = new File(finalDir, fileName);
file.transferTo(dest);
// 5. 相对路径,用于生成URL
String relativePath = PathUtils.joinFilePath(
datePath,
finalDir.getName(),
fileName
);
return fileConfig.buildFileUrl(relativePath);
}
/**
* 多文件上传
*/
public List<String> uploadBatch(MultipartFile[] files, String containerNo, String[] fileNames) throws IOException {
if (files == null || files.length == 0) {
return new ArrayList<>();
}
List<String> urls = new ArrayList<>();
for (int i = 0; i < files.length; i++) {
String name = (fileNames != null && i < fileNames.length) ? fileNames[i] : files[i].getOriginalFilename();
urls.add(upload(files[i], containerNo, name));
}
return urls;
}
/**
* 解析容器目录
* - 如果同一天已存在该箱号目录 -> 自动加 _1/_2/... 避免覆盖
*/
private File resolveContainerDir(String basePath, String containerNo) {
File containerDir = new File(PathUtils.joinFilePath(basePath, containerNo));
if (!containerDir.exists()) {
return containerDir;
}
// 已存在 -> 找下一个可用序号
int i = 1;
while (true) {
File dir = new File(PathUtils.joinFilePath(basePath, containerNo + "_" + i));
if (!dir.exists()) {
return dir;
}
i++;
}
}
}
@@ -0,0 +1,87 @@
package cn.g3soft.utils;
import cn.g3soft.config.FileConfig;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;
@Component
public class FileUploadUtils {
@Resource
private FileConfig fileConfig;
/**
* 上传文件到临时路径
* @param file 上传的文件
* @param fileName 如果前端传递了文件名,使用传递的文件名
* @return 临时文件的URL
*/
public String uploadTemp(MultipartFile file, String fileName) throws IOException {
// 1. 生成最终文件名
String finalFileName = generateTempFileName(file, fileName);
// 2. 临时目录路径
File tempDir = new File(fileConfig.getTempPath());
// 如果临时目录不存在,创建目录
if (!tempDir.exists()) {
tempDir.mkdirs();
}
// 3. 保存文件到临时目录
File tempFile = new File(tempDir, finalFileName);
file.transferTo(tempFile);
// 4. 返回临时文件的 URL(供 OCR 使用)
return fileConfig.buildTempUrl(finalFileName);
}
/**
* 根据文件名生成临时文件名(带时间戳 + UUID + 文件后缀)
* @param file 上传的文件
* @param fileName 传递的文件名(可选)
* @return 生成的最终文件名
*/
private String generateTempFileName(MultipartFile file, String fileName) {
// 优先使用前端传递的 fileName
String originalFilename = (fileName != null && !fileName.isEmpty())
? fileName
: file.getOriginalFilename();
// 如果没有获取到文件名,设置一个默认文件名
if (originalFilename == null) {
originalFilename = "file";
}
// 获取文件后缀
String extension = "";
if (originalFilename.contains(".")) {
extension = originalFilename.substring(originalFilename.lastIndexOf("."));
}
// 生成带时间戳和 UUID 的文件名
return LocalDate.now().format(DateTimeFormatter.BASIC_ISO_DATE) + "_"
+ UUID.randomUUID().toString().replace("-", "") + extension;
}
/**
* 删除临时文件(成功识别后删除)
* @param tempFileName 临时文件的文件名
*/
public void deleteTempFile(String tempFileName) {
String filePath = PathUtils.joinFilePath(fileConfig.getBaseDir(), fileConfig.getTempDir(), tempFileName);
File tempFile = new File(tempFileName);
if (tempFile.exists()) {
tempFile.delete();
}
}
}
@@ -0,0 +1,117 @@
package cn.g3soft.utils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.IOException;
import java.util.UUID;
public class FileUtils {
/**
* =========================
* 最简调用:自动生成文件名 + 不覆盖
* =========================
*/
public static String upload(MultipartFile file, String uploadPath) throws IOException {
return upload(file, uploadPath, null, false);
}
/**
* =========================
* 指定文件名 + 不覆盖
* =========================
*/
public static String upload(MultipartFile file,
String uploadPath,
String fileName) throws IOException {
return upload(file, uploadPath, fileName, false);
}
/**
* =========================
* 控制是否覆盖 + 自动生成文件名
* =========================
*/
public static String upload(MultipartFile file,
String uploadPath,
boolean overwrite) throws IOException {
return upload(file, uploadPath, null, overwrite);
}
/**
* =========================
* 核心方法(唯一执行逻辑)
* =========================
*/
public static String upload(MultipartFile file,
String uploadPath,
String fileName,
boolean overwrite) throws IOException {
// 1. 校验文件
if (file == null || file.isEmpty()) {
throw new RuntimeException("上传文件不能为空");
}
// 2. 创建目录
File dir = new File(uploadPath);
if (!dir.exists()) {
boolean created = dir.mkdirs();
if (!created) {
throw new RuntimeException("目录创建失败: " + uploadPath);
}
}
// 3. 获取原始文件名
String originalName = file.getOriginalFilename();
// 4. 处理文件名
if (fileName == null || fileName.trim().isEmpty()) {
fileName = generateFileName(originalName);
} else {
// 如果用户传了文件名,但没有后缀,则补上
if (!fileName.contains(".") && originalName != null && originalName.contains(".")) {
fileName = fileName + getSuffix(originalName);
}
}
// 5. 目标文件
File dest = new File(dir, fileName);
// 6. 处理覆盖逻辑
if (dest.exists() && !overwrite) {
String newName = generateFileName(fileName);
dest = new File(dir, newName);
fileName = newName;
}
// 7. 保存文件
file.transferTo(dest);
// 8. 返回文件路径(你也可以改成返回 URL)
return dest.getAbsolutePath();
}
/**
* =========================
* 生成唯一文件名
* =========================
*/
private static String generateFileName(String originalName) {
return UUID.randomUUID().toString().replace("-", "")
+ getSuffix(originalName);
}
/**
* =========================
* 获取文件后缀
* =========================
*/
private static String getSuffix(String fileName) {
if (fileName == null || !fileName.contains(".")) {
return "";
}
return fileName.substring(fileName.lastIndexOf("."));
}
}
@@ -1,29 +1,12 @@
package cn.g3soft.utils;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ConnectException;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.security.cert.X509Certificate;
import java.util.Map;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.MediaType;
import okhttp3.*;
/**
* 通用http发送方法
@@ -32,287 +15,92 @@ import org.springframework.http.MediaType;
*/
public class HttpUtils
{
private static final Logger log = LoggerFactory.getLogger(HttpUtils.class);
private static final ObjectMapper MAPPER = new ObjectMapper();
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url)
{
return sendGet(url, StringUtils.EMPTY);
private static final OkHttpClient client = new OkHttpClient.Builder()
.connectTimeout(5, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.writeTimeout(10, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(50, 5, TimeUnit.MINUTES))
.build();
private static final MediaType JSON = MediaType.get("application/json; charset=utf-8");
// ==================== GET ====================
public static String get(String url) throws Exception {
Request request = new Request.Builder()
.url(url)
.get()
.build();
try (Response response = client.newCall(request).execute()) {
return response.body() != null ? response.body().string() : null;
}
}
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param)
{
return sendGet(url, param, "UTF-8");
}
public static String get(String url, Map<String, Object> params, String contentType) throws Exception {
HttpUrl.Builder urlBuilder = Objects.requireNonNull(HttpUrl.parse(url)).newBuilder();
/**
* 向指定 URL 发送GET方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @param contentType 编码类型
* @return 所代表远程资源的响应结果
*/
public static String sendGet(String url, String param, String contentType)
{
StringBuilder result = new StringBuilder();
BufferedReader in = null;
try
{
String urlNameString = StringUtils.isNotBlank(param) ? url + "?" + param : url;
log.info("sendGet - {}", urlNameString);
URL realUrl = new URL(urlNameString);
URLConnection connection = realUrl.openConnection();
connection.setRequestProperty("accept", "*/*");
connection.setRequestProperty("connection", "Keep-Alive");
connection.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
connection.connect();
in = new BufferedReader(new InputStreamReader(connection.getInputStream(), contentType));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendGet ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendGet SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendGet IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendGet Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (in != null)
{
in.close();
if (params != null) {
for (Map.Entry<String, Object> entry : params.entrySet()) {
if (entry.getValue() != null) {
urlBuilder.addQueryParameter(
entry.getKey(),
String.valueOf(entry.getValue())
);
}
}
catch (Exception ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数,请求参数应该是 name1=value1&name2=value2 的形式。
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param)
{
return sendPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
}
/**
* 向指定 URL 发送POST方法的请求
*
* @param url 发送请求的 URL
* @param param 请求参数
* @param contentType 内容类型
* @return 所代表远程资源的响应结果
*/
public static String sendPost(String url, String param, String contentType)
{
PrintWriter out = null;
BufferedReader in = null;
StringBuilder result = new StringBuilder();
try
{
log.info("sendPost - {}", url);
URL realUrl = new URL(url);
URLConnection conn = realUrl.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("Content-Type", contentType);
conn.setDoOutput(true);
conn.setDoInput(true);
out = new PrintWriter(conn.getOutputStream());
out.print(param);
out.flush();
in = new BufferedReader(new InputStreamReader(conn.getInputStream(), StandardCharsets.UTF_8));
String line;
while ((line = in.readLine()) != null)
{
result.append(line);
}
log.info("recv - {}", result);
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendPost Exception, url=" + url + ",param=" + param, e);
}
finally
{
try
{
if (out != null)
{
out.close();
}
if (in != null)
{
in.close();
}
}
catch (IOException ex)
{
log.error("调用in.close Exception, url=" + url + ",param=" + param, ex);
}
}
return result.toString();
}
/**
* 向指定 URL 发送 POST 请求,内容类型为 JSON
*
* @param url 请求的 URL
* @param reqPayload 请求参数,Map 类型
* @return 响应结果
*/
public static String sendPostJson(String url, Map<String, Object> reqPayload) {
// 创建一个 ObjectMapper 实例,用于将 Map 转换为 JSON 字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonParam = null;
try {
// 将 Map 转换为 JSON 字符串
jsonParam = objectMapper.writeValueAsString(reqPayload);
} catch (Exception e) {
log.error("请求参数转换为 JSON 失败,url=" + url, e);
return null;
}
// 调用 sendPost 方法,发送请求并返回响应
return sendPost(url, jsonParam, "application/json");
}
Request.Builder builder = new Request.Builder()
.url(urlBuilder.build())
.get();
public static String sendSSLPost(String url, String param)
{
return sendSSLPost(url, param, MediaType.APPLICATION_FORM_URLENCODED_VALUE);
}
public static String sendSSLPost(String url, String param, String contentType)
{
StringBuilder result = new StringBuilder();
String urlNameString = url + "?" + param;
try
{
log.info("sendSSLPost - {}", urlNameString);
SSLContext sc = SSLContext.getInstance("SSL");
sc.init(null, new TrustManager[] { new TrustAnyTrustManager() }, new java.security.SecureRandom());
URL console = new URL(urlNameString);
HttpsURLConnection conn = (HttpsURLConnection) console.openConnection();
conn.setRequestProperty("accept", "*/*");
conn.setRequestProperty("connection", "Keep-Alive");
conn.setRequestProperty("user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64)");
conn.setRequestProperty("Accept-Charset", "utf-8");
conn.setRequestProperty("Content-Type", contentType);
conn.setDoOutput(true);
conn.setDoInput(true);
conn.setSSLSocketFactory(sc.getSocketFactory());
conn.setHostnameVerifier(new TrustAnyHostnameVerifier());
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String ret = "";
while ((ret = br.readLine()) != null)
{
if (ret != null && !"".equals(ret.trim()))
{
result.append(new String(ret.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8));
}
}
log.info("recv - {}", result);
conn.disconnect();
br.close();
}
catch (ConnectException e)
{
log.error("调用HttpUtils.sendSSLPost ConnectException, url=" + url + ",param=" + param, e);
}
catch (SocketTimeoutException e)
{
log.error("调用HttpUtils.sendSSLPost SocketTimeoutException, url=" + url + ",param=" + param, e);
}
catch (IOException e)
{
log.error("调用HttpUtils.sendSSLPost IOException, url=" + url + ",param=" + param, e);
}
catch (Exception e)
{
log.error("调用HttpsUtil.sendSSLPost Exception, url=" + url + ",param=" + param, e);
}
return result.toString();
}
private static class TrustAnyTrustManager implements X509TrustManager
{
@Override
public void checkClientTrusted(X509Certificate[] chain, String authType)
{
if (contentType != null && !contentType.isEmpty()) {
builder.addHeader("Content-Type", contentType);
}
@Override
public void checkServerTrusted(X509Certificate[] chain, String authType)
{
}
@Override
public X509Certificate[] getAcceptedIssuers()
{
return new X509Certificate[] {};
try (Response response = client.newCall(builder.build()).execute()) {
return response.body() != null ? response.body().string() : null;
}
}
private static class TrustAnyHostnameVerifier implements HostnameVerifier
{
@Override
public boolean verify(String hostname, SSLSession session)
{
return true;
// ==================== POST FORM ====================
public static String postForm(String url, Map<String, String> params) throws Exception {
FormBody.Builder builder = new FormBody.Builder();
for (Map.Entry<String, String> entry : params.entrySet()) {
builder.add(entry.getKey(), entry.getValue());
}
Request request = new Request.Builder()
.url(url)
.post(builder.build())
.build();
try (Response response = client.newCall(request).execute()) {
return response.body() != null ? response.body().string() : null;
}
}
// ==================== POST JSON ====================
// ==================== POST JSON(Map版本)====================
public static String postJson(String url, Map<String, Object> params) throws Exception {
// 1. Map 转 JSON 字符串
String json = MAPPER.writeValueAsString(params);
// 2. 构建请求体
RequestBody body = RequestBody.create(json, JSON);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
// 3. 执行请求
try (Response response = client.newCall(request).execute()) {
return response.body() != null ? response.body().string() : null;
}
}
}
@@ -0,0 +1,42 @@
package cn.g3soft.utils;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathUtils {
public static String joinUrl(String... parts) {
if (parts == null || parts.length == 0) return "";
StringBuilder sb = new StringBuilder();
for (String part : parts) {
if (part == null || part.trim().isEmpty()) continue;
part = part.trim();
if (sb.length() == 0) {
// 第一段:保留协议(http://)
sb.append(part.replaceAll("/+$", ""));
} else {
sb.append("/");
sb.append(part.replaceAll("^/+", "").replaceAll("/+$", ""));
}
}
return sb.toString();
}
public static String joinFilePath(String... paths) {
if (paths == null || paths.length == 0) return "";
Path result = null;
for (String p : paths) {
if (p == null || p.trim().isEmpty()) continue;
if (result == null) {
result = Paths.get(p.trim());
} else {
result = result.resolve(p.trim());
}
}
return (result == null) ? "" : result.normalize().toString();
}
}
@@ -7,6 +7,9 @@ import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.HashMap;
import java.util.Map;
public class AddressUtils
{
private static final Logger log = LoggerFactory.getLogger(AddressUtils.class);
@@ -28,7 +31,12 @@ public class AddressUtils
try
{
String rspStr = HttpUtils.sendGet(IP_URL, "ip=" + ip + "&json=true", "GBK");
Map<String,Object> params = new HashMap<>();
params.put("ip",ip);
params.put("json",true);
String rspStr = HttpUtils.get(IP_URL, params, "GBK");
if (StringUtils.isEmpty(rspStr))
{
log.error("获取地理位置异常 {}", ip);
@@ -1,6 +1,6 @@
server:
servlet:
context-path: /api # 应用的访问路径
context-path: /api # 应用的访问路径
tomcat:
uri-encoding: UTF-8 # URI编码
accept-count: 1000 # 连接数满后的排队数
@@ -16,4 +16,12 @@ spring:
max-request-size: -1
jackson:
time-zone: "Asia/Shanghai"
date-format: yyyy-MM-dd HH:mm:ss
date-format: yyyy-MM-dd HH:mm:ss
file:
static-path: /static/file
server-url: http://192.168.1.137:80/api
base-dir: D:/data
container-dir: container
temp-dir: temp
@@ -3,8 +3,8 @@ username=sa
password=zhang520..
driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
# url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3BoxOCR
# username=sa
# password=123456@aaa
# driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
#url=jdbc:sqlserver://127.0.0.1:1433;databaseName=G3BoxOCR
#username=sa
#password=123456@aaa
#driver=com.microsoft.sqlserver.jdbc.SQLServerDriver
@@ -0,0 +1,84 @@
package cn.g3soft;
import cn.g3soft.utils.HttpUtils;
import cn.g3soft.utils.Result;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertTrue;
@SpringBootTest
public class DEMO {
@Test
public void testHello() throws Exception {
long startTime = System.nanoTime(); // 开始时间
String filePath = "D:\\100全关门-3\\20241005082220A664.jpg"; // 你的图片路径
byte[] fileBytes = Files.readAllBytes(Paths.get(filePath));
// String fileUrl = Base64.getEncoder().encodeToString(fileBytes);
String fileUrl = "http://g3hd.oss-cn-hangzhou.aliyuncs.com/g3hd/2026/03/28/1774665878210_960.jpg";
String requestUrl = "http://127.0.0.1:8867/ocr";
Map<String, Object> reqPayload = new HashMap<>();
reqPayload.put("file", fileUrl);
reqPayload.put("fileType", 1);
reqPayload.put("visualize", false);
try {
String response = HttpUtils.postJson(requestUrl, reqPayload);
ObjectMapper mapper = new ObjectMapper();
JsonNode root = mapper.readTree(response);
JsonNode ocrResults = root.path("result").path("ocrResults");
if (!ocrResults.isArray() || ocrResults.isEmpty()) {
System.out.println("空");
}
String number = "";
double maxScore = -1.0;
for (JsonNode item : ocrResults) {
JsonNode pruned = item.path("prunedResult");
JsonNode recTexts = pruned.path("rec_texts");
JsonNode recScores = pruned.path("rec_scores");
for (int i = 0; i < recTexts.size(); i++) {
double score = recScores.get(i).asDouble();
if (score > maxScore) {
maxScore = score;
number = recTexts.get(i).asText();
}
}
}
Map<String, Object> result = new HashMap<>();
result.put("boxNumber", number);
result.put("score", maxScore);
} catch (Exception e) {
e.printStackTrace();
} finally {
long endTime = System.nanoTime(); // 结束时间
long durationMs = (endTime - startTime) / 1_000_000;
System.out.println("耗时: " + durationMs + " ms");
}
}
}