test(material): 添加物料图片批量上传测试用例
- 从桌面Output文件夹读取所有图片文件进行处理 - 实现图片文件上传到指定接口并获取图片URL - 根据文件名无后缀匹配物料编号查找对应记录 - 更新物料表中对应记录的图片URL字段 - 处理上传及更新过程中的异常情况并统计结果 - 递归收集支持多种图片格式的文件 - 额外实现递归目录删除辅助方法
This commit is contained in:
parent
c643d26632
commit
17f78cc9ba
|
|
@ -0,0 +1,210 @@
|
||||||
|
package com.nflg.wms.shipment;
|
||||||
|
|
||||||
|
import cn.hutool.core.io.FileUtil;
|
||||||
|
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||||
|
import com.nflg.wms.repository.entity.WmsShipmentMaterial;
|
||||||
|
import com.nflg.wms.repository.mapper.WmsShipmentMaterialMapper;
|
||||||
|
import jakarta.annotation.Resource;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
import org.springframework.boot.test.context.SpringBootTest;
|
||||||
|
import org.springframework.core.io.FileSystemResource;
|
||||||
|
import org.springframework.http.*;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
|
import org.springframework.util.MultiValueMap;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 物料图片批量上传测试
|
||||||
|
* 从桌面的Output文件夹读取所有图片并上传,然后更新物料表的image字段
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@SpringBootTest
|
||||||
|
@ContextConfiguration(classes = ShipmentApplication.class)
|
||||||
|
public class MaterialImageUploadTest {
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private WmsShipmentMaterialMapper materialMapper;
|
||||||
|
|
||||||
|
@Resource
|
||||||
|
private RestTemplate restTemplate;
|
||||||
|
|
||||||
|
// 文件上传接口地址
|
||||||
|
private static final String UPLOAD_URL = "https://pomp.nflg.net/api/admin/file/uploadSingleFile1";
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUploadImagesFromZip() {
|
||||||
|
// 桌面路径
|
||||||
|
String desktopPath = System.getProperty("user.home") + File.separator + "Desktop";
|
||||||
|
String outputDirPath = desktopPath + File.separator + "Output";
|
||||||
|
|
||||||
|
log.info("开始处理Output文件夹: {}", outputDirPath);
|
||||||
|
|
||||||
|
// 检查文件夹是否存在
|
||||||
|
File outputDir = new File(outputDirPath);
|
||||||
|
if (!outputDir.exists()) {
|
||||||
|
log.error("Output文件夹不存在: {}", outputDirPath);
|
||||||
|
throw new RuntimeException("Output文件夹不存在: " + outputDirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outputDir.isDirectory()) {
|
||||||
|
log.error("路径不是文件夹: {}", outputDirPath);
|
||||||
|
throw new RuntimeException("路径不是文件夹: " + outputDirPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 递归获取所有图片文件
|
||||||
|
java.util.List<File> imageFiles = new java.util.ArrayList<>();
|
||||||
|
collectImageFiles(outputDir, imageFiles);
|
||||||
|
|
||||||
|
if (imageFiles.isEmpty()) {
|
||||||
|
log.warn("Output文件夹中没有找到图片文件");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.info("找到 {} 个图片文件", imageFiles.size());
|
||||||
|
|
||||||
|
// 处理每个图片文件
|
||||||
|
int successCount = 0;
|
||||||
|
int notFoundCount = 0;
|
||||||
|
int errorCount = 0;
|
||||||
|
|
||||||
|
for (File imageFile : imageFiles) {
|
||||||
|
try {
|
||||||
|
// 获取文件名(不带后缀)
|
||||||
|
String fileNameWithoutExt = FileUtil.getPrefix(imageFile.getName());
|
||||||
|
log.info("处理文件: {}, 文件名(无后缀): {}", imageFile.getName(), fileNameWithoutExt);
|
||||||
|
|
||||||
|
// 上传文件
|
||||||
|
String url = uploadFile(imageFile);
|
||||||
|
log.info("文件上传成功, url: {}", url);
|
||||||
|
|
||||||
|
// 根据no字段查找物料
|
||||||
|
WmsShipmentMaterial material = materialMapper.selectOne(
|
||||||
|
new com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper<WmsShipmentMaterial>()
|
||||||
|
.eq(WmsShipmentMaterial::getNo, fileNameWithoutExt)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (material != null) {
|
||||||
|
// 更新image字段
|
||||||
|
LambdaUpdateWrapper<WmsShipmentMaterial> updateWrapper = new LambdaUpdateWrapper<>();
|
||||||
|
updateWrapper.eq(WmsShipmentMaterial::getNo, fileNameWithoutExt)
|
||||||
|
.set(WmsShipmentMaterial::getImage, url);
|
||||||
|
|
||||||
|
int updateCount = materialMapper.update(null, updateWrapper);
|
||||||
|
if (updateCount > 0) {
|
||||||
|
imageFile.delete();
|
||||||
|
log.info("成功更新物料 {} 的图片url", fileNameWithoutExt);
|
||||||
|
successCount++;
|
||||||
|
} else {
|
||||||
|
log.error("更新物料 {} 的图片url失败", fileNameWithoutExt);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.warn("未找到物料编号为 {} 的物料记录", fileNameWithoutExt);
|
||||||
|
notFoundCount++;
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("处理文件 {} 时发生错误: {}", imageFile.getName(), e.getMessage(), e);
|
||||||
|
errorCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 输出统计信息
|
||||||
|
log.info("========================================");
|
||||||
|
log.info("处理完成!");
|
||||||
|
log.info("总文件数: {}", imageFiles.size());
|
||||||
|
log.info("成功更新: {}", successCount);
|
||||||
|
log.info("未找到物料: {}", notFoundCount);
|
||||||
|
log.info("处理错误: {}", errorCount);
|
||||||
|
log.info("========================================");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 上传文件 - 调用HTTP接口
|
||||||
|
*/
|
||||||
|
private String uploadFile(File file) {
|
||||||
|
// 构建multipart请求
|
||||||
|
HttpHeaders headers = new HttpHeaders();
|
||||||
|
headers.setContentType(MediaType.MULTIPART_FORM_DATA);
|
||||||
|
headers.add("authorization", "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJsb2dpblR5cGUiOiJsb2dpbiIsImxvZ2luSWQiOjEsInJuU3RyIjoiM3pCT2dQT203ZmZTVEY5S0gxYldaZ0w0ZmJGVW85TnoiLCJuYW1lIjoi6LaF57qn566h55CG5ZGYIiwiY29kZSI6ImFkbWluIiwicm9sZXMiOlsiU3VwZXJBZG1pbiJdLCJ0eXBlIjoxfQ.Ircp8zNaLX7Wly7IZxEEdQrFo2BVfufXxXDhn7wSdrk");
|
||||||
|
|
||||||
|
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
||||||
|
body.add("file", new FileSystemResource(file));
|
||||||
|
|
||||||
|
HttpEntity<MultiValueMap<String, Object>> requestEntity = new HttpEntity<>(body, headers);
|
||||||
|
|
||||||
|
// 使用String接收响应,避免Jackson反序列化LocalDateTime的问题
|
||||||
|
ResponseEntity<String> responseEntity = restTemplate.postForEntity(UPLOAD_URL, requestEntity, String.class);
|
||||||
|
|
||||||
|
// 检查响应
|
||||||
|
if (responseEntity.getStatusCode() != HttpStatus.OK || responseEntity.getBody() == null) {
|
||||||
|
throw new RuntimeException("文件上传失败,HTTP状态码: " + responseEntity.getStatusCode());
|
||||||
|
}
|
||||||
|
|
||||||
|
// 手动解析JSON
|
||||||
|
String responseBody = responseEntity.getBody();
|
||||||
|
log.debug("上传响应: {}", responseBody);
|
||||||
|
|
||||||
|
cn.hutool.json.JSONObject jsonObject = cn.hutool.json.JSONUtil.parseObj(responseBody);
|
||||||
|
int code = jsonObject.getInt("code", -1);
|
||||||
|
|
||||||
|
if (code != 200) {
|
||||||
|
String message = jsonObject.getStr("message", "未知错误");
|
||||||
|
throw new RuntimeException("文件上传失败: " + message);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 提取url
|
||||||
|
cn.hutool.json.JSONObject result = jsonObject.getJSONObject("result");
|
||||||
|
if (result == null) {
|
||||||
|
throw new RuntimeException("文件上传失败: 返回结果为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
String url = result.getStr("url");
|
||||||
|
if (url == null || url.isEmpty()) {
|
||||||
|
throw new RuntimeException("文件上传失败: URL为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归收集所有图片文件
|
||||||
|
*/
|
||||||
|
private void collectImageFiles(File dir, java.util.List<File> imageFiles) {
|
||||||
|
File[] files = dir.listFiles();
|
||||||
|
if (files == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
collectImageFiles(file, imageFiles);
|
||||||
|
} else {
|
||||||
|
String lowerName = file.getName().toLowerCase();
|
||||||
|
if (lowerName.endsWith(".jpg") || lowerName.endsWith(".jpeg") ||
|
||||||
|
lowerName.endsWith(".png") || lowerName.endsWith(".gif") ||
|
||||||
|
lowerName.endsWith(".bmp")) {
|
||||||
|
imageFiles.add(file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 递归删除目录
|
||||||
|
*/
|
||||||
|
private void deleteDirectory(File file) {
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
if (files != null) {
|
||||||
|
for (File f : files) {
|
||||||
|
deleteDirectory(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue