feat(doc): 添加文档分类和篡改检测功能支持base64图片上传
- 在BaseController中新增normalizeBase64Image方法处理多种base64图片格式 - 重构DocClassifyController支持imageBase64参数并添加URL编码处理 - 将ForgeryDetectionController从命令模式改为直接调用百度API - 添加URLEncoder对图片参数进行编码防止传输错误 - 新增ForgeDetectionController的完整单元测试覆盖多种场景 - 添加DocClassifyController的base64图片上传测试用例 - 创建TestConstant统一管理测试用的图片资源 - 移除不再使用的内部DTO转换逻辑简化代码结构
This commit is contained in:
parent
67e18b4fa3
commit
894c3124ac
@ -55,6 +55,34 @@ public class BaseController {
|
||||
return value == null || value.trim().length() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* 规范化 base64 图片输入,兼容多种常见格式:
|
||||
* <ul>
|
||||
* <li>data:image/png;base64,xxxx(Data URI 格式,自动剥离前缀)</li>
|
||||
* <li>data:image/jpeg;base64,xxxx(同理)</li>
|
||||
* <li>纯 base64 字符串(直接保留)</li>
|
||||
* <li>含换行/空白字符的 base64(自动清除)</li>
|
||||
* </ul>
|
||||
*
|
||||
* @param imageBase64 原始输入
|
||||
* @return 清理后的纯 base64 字符串
|
||||
*/
|
||||
protected String normalizeBase64Image(String imageBase64) {
|
||||
if (imageBase64 == null) {
|
||||
return null;
|
||||
}
|
||||
// 剥离 data:image/xxx;base64, 前缀
|
||||
String value = imageBase64.trim();
|
||||
if (value.regionMatches(true, 0, "data:", 0, 5)) {
|
||||
int commaIdx = value.indexOf(',');
|
||||
if (commaIdx >= 0) {
|
||||
value = value.substring(commaIdx + 1);
|
||||
}
|
||||
}
|
||||
// 清除 base64 中常见的换行和空白
|
||||
return value.replaceAll("[\\s\\r\\n]", "");
|
||||
}
|
||||
|
||||
protected Map<String, Object> requestBaidu(String uri, String content) {
|
||||
String result = null;
|
||||
try {
|
||||
|
||||
@ -11,6 +11,7 @@ import com.heyu.api.data.utils.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
|
||||
/***
|
||||
@ -45,7 +46,12 @@ public class DocClassifyController extends BaseController {
|
||||
if (request == null || (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl()))) {
|
||||
return R.error("image 和 url 不能都为空");
|
||||
}
|
||||
String content = buildContent(request);
|
||||
String content;
|
||||
try {
|
||||
content = buildContent(request);
|
||||
} catch (Exception e) {
|
||||
return R.error("参数编码失败");
|
||||
}
|
||||
Map<String, Object> result = requestBaidu(DOC_CLASSIFY_URI, content);
|
||||
if (result == null) {
|
||||
return R.error("识别失败");
|
||||
@ -55,13 +61,13 @@ public class DocClassifyController extends BaseController {
|
||||
return R.ok().setData(resp);
|
||||
}
|
||||
|
||||
private String buildContent(BDocClassifyRequest request) {
|
||||
private String buildContent(BDocClassifyRequest request) throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.isNotBlank(request.getImageBase64())) {
|
||||
sb.append("&image=").append(request.getImageBase64());
|
||||
sb.append("&image=").append(URLEncoder.encode(normalizeBase64Image(request.getImageBase64()), "UTF-8"));
|
||||
}
|
||||
if (StringUtils.isNotBlank(request.getImageUrl())) {
|
||||
sb.append("&url=").append(request.getImageUrl());
|
||||
sb.append("&url=").append(URLEncoder.encode(request.getImageUrl(), "UTF-8"));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@ -1,23 +1,21 @@
|
||||
package com.heyu.api.controller.doc;
|
||||
|
||||
import com.heyu.api.baidu.handle.doc.BForgeryDetectionHandle;
|
||||
import com.heyu.api.baidu.request.doc.BForgeryDetectionRequest;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import com.heyu.api.baidu.response.doc.BForgeryDetectionResp;
|
||||
import com.heyu.api.controller.BaseController;
|
||||
import com.heyu.api.data.annotation.EbAuthentication;
|
||||
import com.heyu.api.data.annotation.NotIntercept;
|
||||
import com.heyu.api.data.constants.ApiConstants;
|
||||
import com.heyu.api.data.utils.ApiR;
|
||||
import com.heyu.api.data.utils.R;
|
||||
import com.heyu.api.data.utils.StringUtils;
|
||||
import com.heyu.api.request.doc.ForgeryDetectionRequest;
|
||||
import com.heyu.api.resp.doc.ForgeryDetectionResp;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.net.URLEncoder;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 图片篡改检测
|
||||
@ -27,82 +25,59 @@ import java.util.List;
|
||||
* 支持对图像中的伪造区域以热力图形式进行可视化返回。
|
||||
*
|
||||
* 百度文档:https://cloud.baidu.com/doc/OCR/s/kmfdnccok
|
||||
*
|
||||
* @author zhengli
|
||||
* @since 20260607_zl
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/doc")
|
||||
@NotIntercept
|
||||
public class ForgeryDetectionController {
|
||||
public class ForgeryDetectionController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
private BForgeryDetectionHandle bForgeryDetectionHandle;
|
||||
private static final String FORGERY_DETECTION_URI = "rest/2.0/ocr/v1/forgery_detection";
|
||||
|
||||
/**
|
||||
* 图片篡改检测
|
||||
* @param request: {"detectProportion":"true","detectThreshold":"0.9887","imageUrl":"https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png","restrictProbability":"0.8","returnHeatmap":"true"}
|
||||
* @return
|
||||
*
|
||||
* 假设(Given) + 当(When) + 则(Then):
|
||||
* - Given: 传入 imageBase64 或 imageUrl(二选一)
|
||||
* - When: 调用百度篡改检测API(使用默认参数)
|
||||
* - Then: 返回篡改检测结果,包含 detectionResult、tamperedLocation 等
|
||||
*
|
||||
* @param request {"imageBase64": "...", "imageUrl": "..."}
|
||||
* @return 篡改检测结果
|
||||
*/
|
||||
@EbAuthentication(tencent = ApiConstants.TENCENT_AUTH)
|
||||
@PostMapping("/forgeryDetection")
|
||||
public R<ForgeryDetectionResp> forgeryDetection(ForgeryDetectionRequest request) {
|
||||
long start = System.currentTimeMillis();
|
||||
|
||||
BForgeryDetectionRequest bRequest = toBaiduRequest(request);
|
||||
|
||||
ApiR<BForgeryDetectionResp> bR = bForgeryDetectionHandle.handle(bRequest);
|
||||
if (!bR.isSuccess()) {
|
||||
log.info("图片篡改检测-失败, error:{}, 耗时:{}ms", bR.getErrorMsg(), System.currentTimeMillis() - start);
|
||||
return R.error(bR.getErrorMsg());
|
||||
public R<BForgeryDetectionResp> forgeryDetection(ForgeryDetectionRequest request) {
|
||||
if (request == null || (isBlank(request.getImageBase64()) && isBlank(request.getImageUrl()))) {
|
||||
return R.error("image 和 url 不能都为空");
|
||||
}
|
||||
|
||||
BForgeryDetectionResp bResp = bR.getData();
|
||||
if (bResp.getResult() == null) {
|
||||
log.info("图片篡改检测-结果为空, 耗时:{}ms", System.currentTimeMillis() - start);
|
||||
return R.error("图片篡改检测结果为空");
|
||||
String content;
|
||||
try {
|
||||
content = buildContent(request);
|
||||
} catch (Exception e) {
|
||||
log.error("forgeryDetection buildContent 异常", e);
|
||||
return R.error("参数编码失败");
|
||||
}
|
||||
|
||||
ForgeryDetectionResp resp = toResp(bResp);
|
||||
|
||||
log.info("图片篡改检测-完成, 耗时:{}ms", System.currentTimeMillis() - start);
|
||||
Map<String, Object> result = requestBaidu(FORGERY_DETECTION_URI, content);
|
||||
if (result == null) {
|
||||
return R.error("识别失败");
|
||||
}
|
||||
BForgeryDetectionResp resp = JSONObject.parseObject(
|
||||
JSONObject.toJSONString(result), BForgeryDetectionResp.class);
|
||||
return R.ok().setData(resp);
|
||||
}
|
||||
|
||||
private BForgeryDetectionRequest toBaiduRequest(ForgeryDetectionRequest request) {
|
||||
BForgeryDetectionRequest bRequest = new BForgeryDetectionRequest();
|
||||
if (request == null) {
|
||||
return bRequest;
|
||||
private String buildContent(ForgeryDetectionRequest request) throws Exception {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
if (StringUtils.isNotBlank(request.getImageBase64())) {
|
||||
sb.append("&image=").append(URLEncoder.encode(normalizeBase64Image(request.getImageBase64()), "UTF-8"));
|
||||
}
|
||||
bRequest.setImageBase64(request.getImageBase64());
|
||||
bRequest.setImageUrl(request.getImageUrl());
|
||||
bRequest.setDetectProportion(request.getDetectProportion());
|
||||
bRequest.setDetectThreshold(request.getDetectThreshold());
|
||||
bRequest.setReturnHeatmap(request.getReturnHeatmap());
|
||||
bRequest.setRestrictProbability(request.getRestrictProbability());
|
||||
return bRequest;
|
||||
}
|
||||
|
||||
private ForgeryDetectionResp toResp(BForgeryDetectionResp bResp) {
|
||||
ForgeryDetectionResp resp = new ForgeryDetectionResp();
|
||||
BForgeryDetectionResp.ResultDTO result = bResp.getResult();
|
||||
|
||||
resp.setDetectionResult(result.getDetectionResult());
|
||||
resp.setTamperedProportion(result.getTamperedProportion());
|
||||
resp.setHeatmap(result.getHeatmap());
|
||||
|
||||
if (result.getTamperedLocation() != null) {
|
||||
List<ForgeryDetectionResp.TamperedLocation> locations = new ArrayList<>();
|
||||
for (BForgeryDetectionResp.TamperedLocationDTO dto : result.getTamperedLocation()) {
|
||||
ForgeryDetectionResp.TamperedLocation location = new ForgeryDetectionResp.TamperedLocation();
|
||||
location.setLeft(dto.getLeft());
|
||||
location.setTop(dto.getTop());
|
||||
location.setWidth(dto.getWidth());
|
||||
location.setHeight(dto.getHeight());
|
||||
location.setProbability(dto.getProbability());
|
||||
locations.add(location);
|
||||
}
|
||||
resp.setTamperedLocation(locations);
|
||||
if (StringUtils.isNotBlank(request.getImageUrl())) {
|
||||
sb.append("&url=").append(URLEncoder.encode(request.getImageUrl(), "UTF-8"));
|
||||
}
|
||||
|
||||
return resp;
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@ -4,6 +4,9 @@ import lombok.Data;
|
||||
|
||||
/**
|
||||
* 图片篡改检测 - 前端请求参数
|
||||
*
|
||||
* @author zhengli
|
||||
* @since 20260607_zl
|
||||
*/
|
||||
@Data
|
||||
public class ForgeryDetectionRequest {
|
||||
@ -19,28 +22,4 @@ public class ForgeryDetectionRequest {
|
||||
* 和 imageBase64 二选一
|
||||
*/
|
||||
private String imageUrl;
|
||||
|
||||
/**
|
||||
* 是否返回图片篡改置信度
|
||||
* - true:返回
|
||||
* - false:不返回(默认)
|
||||
*/
|
||||
private String detectProportion;
|
||||
|
||||
/**
|
||||
* 图片篡改检出阈值,范围0.0001~1,默认为0.9887
|
||||
*/
|
||||
private String detectThreshold;
|
||||
|
||||
/**
|
||||
* 是否返回伪造区域热力图
|
||||
* - true:返回热力图base64编码
|
||||
* - false:不返回(默认)
|
||||
*/
|
||||
private String returnHeatmap;
|
||||
|
||||
/**
|
||||
* 返回伪造区域坐标的阈值,范围0.1~1,默认为0.8
|
||||
*/
|
||||
private String restrictProbability;
|
||||
}
|
||||
|
||||
20
api-web/api-interface/src/test/java/com/TestConstant.java
Normal file
20
api-web/api-interface/src/test/java/com/TestConstant.java
Normal file
@ -0,0 +1,20 @@
|
||||
package com;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
public class TestConstant {
|
||||
|
||||
public static final String TARGET_IMAGE_URL = "https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png";
|
||||
public static final String TARGET_IMAGE_BASE64;
|
||||
static {
|
||||
try {
|
||||
Path path = Paths.get("src/test/resources/image_base64.txt");
|
||||
TARGET_IMAGE_BASE64 = "data:image/png;base64," + new String(Files.readAllBytes(path), StandardCharsets.UTF_8).trim();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load image_base64.txt", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,7 @@
|
||||
package com.heyu.api.controller.doc;
|
||||
|
||||
import com.ApiInterfaceApplicationTests;
|
||||
import com.TestConstant;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.heyu.api.baidu.request.doc.BDocClassifyRequest;
|
||||
import com.heyu.api.baidu.response.doc.BDocClassifyResp;
|
||||
@ -10,6 +11,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
/**
|
||||
* 文件检测分类 - 在线图片验证
|
||||
@ -28,13 +30,12 @@ public class DocClassifyControllerTest extends ApiInterfaceApplicationTests {
|
||||
@Autowired
|
||||
private DocClassifyController docClassifyController;
|
||||
|
||||
private static final String TARGET_IMAGE_URL = "https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png";
|
||||
|
||||
@Test
|
||||
void classifyByUrlTest() {
|
||||
// 1. 构造请求
|
||||
BDocClassifyRequest request = new BDocClassifyRequest();
|
||||
request.setImageUrl(TARGET_IMAGE_URL);
|
||||
request.setImageUrl(TestConstant.TARGET_IMAGE_URL);
|
||||
|
||||
// 2. 打印请求参数
|
||||
System.out.println("\n========== 请求参数 ==========");
|
||||
@ -75,4 +76,73 @@ public class DocClassifyControllerTest extends ApiInterfaceApplicationTests {
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
assertEquals("400", result.getCode(), "参数为空时应返回失败");
|
||||
}
|
||||
|
||||
/**
|
||||
* 假设(Given): 本地存在 base64 编码的测试图片
|
||||
* 当(When): 调用 classify 接口,传入 imageBase64 参数
|
||||
* 则(Then): 返回成功的分类检测结果
|
||||
*/
|
||||
@Test
|
||||
void classifyByBase64Test() {
|
||||
// 1. 构造请求 - 使用 base64 图片
|
||||
BDocClassifyRequest request = new BDocClassifyRequest();
|
||||
request.setImageBase64(TestConstant.TARGET_IMAGE_BASE64);
|
||||
|
||||
// 2. 调用接口
|
||||
R<BDocClassifyResp> result = docClassifyController.classify(request);
|
||||
|
||||
// 3. 断言
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
assertEquals("200", result.getCode(), "base64 传图应返回成功");
|
||||
assertNotNull(result.getData(), "返回数据不能为空");
|
||||
|
||||
System.out.println("\n========== base64 分类结果 ==========");
|
||||
System.out.println(JSON.toJSONString(result));
|
||||
System.out.println("====================================");
|
||||
}
|
||||
|
||||
/**
|
||||
* 假设(Given): 同时传入 imageBase64 和 imageUrl
|
||||
* 当(When): 调用 classify 接口
|
||||
* 则(Then): 接口正常返回成功(image 优先级更高)
|
||||
*/
|
||||
@Test
|
||||
void classifyByBase64AndUrlBothTest() {
|
||||
// 1. 构造请求 - 同时传入 base64 和 url
|
||||
BDocClassifyRequest request = new BDocClassifyRequest();
|
||||
request.setImageBase64(TestConstant.TARGET_IMAGE_BASE64);
|
||||
request.setImageUrl(TestConstant.TARGET_IMAGE_URL);
|
||||
|
||||
// 2. 调用接口
|
||||
R<BDocClassifyResp> result = docClassifyController.classify(request);
|
||||
|
||||
// 3. 断言
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
assertEquals("200", result.getCode(), "同时传 base64 和 url 应返回成功");
|
||||
assertNotNull(result.getData(), "返回数据不能为空");
|
||||
}
|
||||
|
||||
/**
|
||||
* 假设(Given): imageBase64 传入无效数据(非 base64 字符串)
|
||||
* 当(When): 调用 classify 接口
|
||||
* 则(Then): 百度 API 返回识别失败
|
||||
*/
|
||||
@Test
|
||||
void classifyByInvalidBase64Test() {
|
||||
// 1. 构造请求 - 传入无效 base64
|
||||
BDocClassifyRequest request = new BDocClassifyRequest();
|
||||
request.setImageBase64("invalid_base64_data_not_an_image");
|
||||
|
||||
// 2. 调用接口
|
||||
R<BDocClassifyResp> result = docClassifyController.classify(request);
|
||||
|
||||
// 3. 断言 - 百度 API 会返回错误,接口应包装为非200或返回错误信息
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
// 无效图片百度会返回错误码,不一定是200
|
||||
assertTrue(result.getCode() != null, "返回 code 不能为空");
|
||||
|
||||
System.out.println("\n========== 无效 base64 结果 ==========");
|
||||
System.out.println(JSON.toJSONString(result));
|
||||
System.out.println("=====================================");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,10 +1,10 @@
|
||||
package com.heyu.api.controller.doc;
|
||||
|
||||
import com.ApiInterfaceApplicationTests;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.TestConstant;
|
||||
import com.heyu.api.baidu.response.doc.BForgeryDetectionResp;
|
||||
import com.heyu.api.data.utils.R;
|
||||
import com.heyu.api.request.doc.ForgeryDetectionRequest;
|
||||
import com.heyu.api.resp.doc.ForgeryDetectionResp;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
@ -12,75 +12,97 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
/**
|
||||
* 图片篡改检测 - 在线图片验证
|
||||
*
|
||||
* 调用本地 /doc/forgeryDetection 接口,验证目标图片是否被篡改。
|
||||
*
|
||||
* 假设(Given): 目标图片可访问,百度 API 可用
|
||||
* 当(When): 调用 forgeryDetection 接口,所有参数开启
|
||||
* 则(Then): 返回检测结果
|
||||
* 图片篡改检测 - 单元测试
|
||||
*
|
||||
* @author zhengli
|
||||
* @since 20260528_zl
|
||||
* @since 20260607_zl
|
||||
*/
|
||||
public class ForgeryDetectionControllerTest extends ApiInterfaceApplicationTests {
|
||||
|
||||
@Autowired
|
||||
private ForgeryDetectionController forgeryDetectionController;
|
||||
|
||||
private static final String TARGET_IMAGE_URL = "https://www.opsky.com.cn/upload/20211224/KXfgvm2MFRAXKbPu5LK.png";
|
||||
|
||||
/**
|
||||
* 验证:传入 imageUrl 调用百度篡改检测(使用默认参数)
|
||||
*
|
||||
* 假设(Given): 百度 API 可用,目标图片可访问
|
||||
* 当(When): 只传 imageUrl,不传可选参数
|
||||
* 则(Then): 返回 code=200,data 非 null,result 中有 detectionResult
|
||||
*/
|
||||
@Test
|
||||
void forgeryDetectionAllParamsTest() {
|
||||
// 1. 构造请求 - 所有参数开启
|
||||
void forgeryDetectionWithImageUrlTest() {
|
||||
// Arrange
|
||||
ForgeryDetectionRequest request = new ForgeryDetectionRequest();
|
||||
request.setImageUrl(TARGET_IMAGE_URL);
|
||||
request.setDetectProportion("true");
|
||||
request.setDetectThreshold("0.9887");
|
||||
request.setReturnHeatmap("true");
|
||||
request.setRestrictProbability("0.8");
|
||||
request.setImageUrl(TestConstant.TARGET_IMAGE_URL);
|
||||
|
||||
// 2. 打印请求参数
|
||||
System.out.println("\n========== 请求参数 ==========");
|
||||
System.out.println(JSON.toJSONString(request));
|
||||
System.out.println("==============================");
|
||||
// Act
|
||||
R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
|
||||
|
||||
// 3. 调用本地 /doc/forgeryDetection 接口
|
||||
R<ForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
|
||||
|
||||
// 4. 打印响应结果
|
||||
System.out.println("\n========== 响应结果 ==========");
|
||||
System.out.println(JSON.toJSONString(result));
|
||||
System.out.println("==============================");
|
||||
|
||||
// 5. 断言
|
||||
// Assert
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
assertEquals("200", result.getCode(), "接口应返回成功");
|
||||
assertNotNull(result.getData(), "返回数据不能为空");
|
||||
assertNotNull(result.getData().getResult(), "百度返回的 result 不能为空");
|
||||
assertNotNull(result.getData().getResult().getDetectionResult(), "检测结果 detectionResult 不能为空");
|
||||
}
|
||||
|
||||
// 6. 打印接口返回值
|
||||
ForgeryDetectionResp data = result.getData();
|
||||
String heatmapDisplay = data.getHeatmap() != null
|
||||
? data.getHeatmap().substring(0, Math.min(50, data.getHeatmap().length())) + "...(共" + data.getHeatmap().length() + "字符)"
|
||||
: "null";
|
||||
/**
|
||||
* 验证:传入 imageBase64 调用百度篡改检测(使用默认参数)
|
||||
*
|
||||
* 假设(Given): 百度 API 可用,imageBase64 为有效图片
|
||||
* 当(When): 只传 imageBase64,不传可选参数
|
||||
* 则(Then): 返回 code=200,data 非 null,result 中有 detectionResult
|
||||
*/
|
||||
@Test
|
||||
void forgeryDetectionWithImageBase64Test() {
|
||||
ForgeryDetectionRequest request = new ForgeryDetectionRequest();
|
||||
request.setImageBase64(TestConstant.TARGET_IMAGE_BASE64);
|
||||
|
||||
System.out.println("\n========== /doc/forgeryDetection 接口返回 ==========");
|
||||
System.out.println("{\"code\":\"" + result.getCode() + "\",");
|
||||
System.out.println(" \"msg\":\"" + result.getMsg() + "\",");
|
||||
System.out.println(" \"data\":{");
|
||||
System.out.println(" \"detectionResult\":\"" + data.getDetectionResult() + "\",");
|
||||
System.out.println(" \"tamperedProportion\":" + data.getTamperedProportion() + ",");
|
||||
System.out.println(" \"heatmap\":\"" + heatmapDisplay + "\",");
|
||||
System.out.println(" \"tamperedLocation\":" + JSON.toJSONString(data.getTamperedLocation()));
|
||||
System.out.println(" }");
|
||||
System.out.println("}");
|
||||
System.out.println("====================================================");
|
||||
// Act
|
||||
R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
|
||||
|
||||
// 结论
|
||||
if ("fake".equals(data.getDetectionResult())) {
|
||||
System.out.println(">>> 结论: 图片【已被篡改】,篡改置信度: " + data.getTamperedProportion());
|
||||
} else {
|
||||
System.out.println(">>> 结论: 图片【未被篡改】,篡改置信度: " + data.getTamperedProportion());
|
||||
}
|
||||
// Assert
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
assertEquals("200", result.getCode(), "接口应返回成功");
|
||||
assertNotNull(result.getData(), "返回数据不能为空");
|
||||
assertNotNull(result.getData().getResult(), "百度返回的 result 不能为空");
|
||||
assertNotNull(result.getData().getResult().getDetectionResult(), "检测结果 detectionResult 不能为空");
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证:image 和 url 都为空时返回错误
|
||||
*
|
||||
* 假设(Given): 不传 imageBase64 也不传 imageUrl
|
||||
* 当(When): 调用接口
|
||||
* 则(Then): 返回 code=400,msg 包含错误信息
|
||||
*/
|
||||
@Test
|
||||
void forgeryDetectionEmptyParamsTest() {
|
||||
// Arrange
|
||||
ForgeryDetectionRequest request = new ForgeryDetectionRequest();
|
||||
|
||||
// Act
|
||||
R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(request);
|
||||
|
||||
// Assert
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
assertEquals("400", result.getCode(), "参数为空应返回 400");
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证:request 为 null 时返回错误
|
||||
*
|
||||
* 假设(Given): request 为 null
|
||||
* 当(When): 调用接口
|
||||
* 则(Then): 返回 code=400
|
||||
*/
|
||||
@Test
|
||||
void forgeryDetectionNullRequestTest() {
|
||||
// Act
|
||||
R<BForgeryDetectionResp> result = forgeryDetectionController.forgeryDetection(null);
|
||||
|
||||
// Assert
|
||||
assertNotNull(result, "返回结果不能为空");
|
||||
assertEquals("400", result.getCode(), "request 为 null 应返回 400");
|
||||
}
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
Loading…
x
Reference in New Issue
Block a user