Compare commits
2 Commits
b44214f74a
...
5acb3a34e0
| Author | SHA1 | Date | |
|---|---|---|---|
| 5acb3a34e0 | |||
| 9dc9bff8b1 |
47
src/main/java/com/corewing/app/dto/api/TrajectoryData.java
Normal file
47
src/main/java/com/corewing/app/dto/api/TrajectoryData.java
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
package com.corewing.app.dto.api;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class TrajectoryData {
|
||||||
|
private Long id;
|
||||||
|
private Long session_id;
|
||||||
|
private Long timestamp;
|
||||||
|
|
||||||
|
// 基础遥测数据
|
||||||
|
private Long rc;
|
||||||
|
private Long gps;
|
||||||
|
private Long gps_status;
|
||||||
|
private double voltage;
|
||||||
|
private double cell_voltage;
|
||||||
|
private Long consumption;
|
||||||
|
private double current;
|
||||||
|
private double speed;
|
||||||
|
private double air_speed;
|
||||||
|
private double v_speed;
|
||||||
|
private double altitude;
|
||||||
|
private double distance;
|
||||||
|
private double range;
|
||||||
|
private Long throttle;
|
||||||
|
private Long wind_direction;
|
||||||
|
private double wind_speed;
|
||||||
|
private Long heading;
|
||||||
|
private double roll;
|
||||||
|
private double pitch;
|
||||||
|
private double yaw;
|
||||||
|
|
||||||
|
// 扩展数据
|
||||||
|
private double compass_heading;
|
||||||
|
private double drone_lat;
|
||||||
|
private double drone_lon;
|
||||||
|
private double home_lat;
|
||||||
|
private double home_lon;
|
||||||
|
private String map_type;
|
||||||
|
private Boolean show_trajectory;
|
||||||
|
private String flight_mode;
|
||||||
|
private Long vehicle_type;
|
||||||
|
private Long autopilot_type;
|
||||||
|
private Boolean is_armed;
|
||||||
|
|
||||||
|
private String sync_id;
|
||||||
|
}
|
||||||
@@ -11,57 +11,16 @@ public class uploadReplaySessionRequest {
|
|||||||
private Long id;
|
private Long id;
|
||||||
private String name;
|
private String name;
|
||||||
private String description;
|
private String description;
|
||||||
private Long startTime;
|
private Long start_time;
|
||||||
private Long endTime;
|
private Long end_time;
|
||||||
private Long duration; // 持续时间(秒)
|
private Long duration; // 持续时间(秒)
|
||||||
private Long dataCount; // 数据点数量
|
private Long data_count; // 数据点数量
|
||||||
private Date createdAt;
|
private Date created_at;
|
||||||
private Date updatedAt;
|
private Date updated_at;
|
||||||
|
private String sync_id;
|
||||||
List<TrajectoryData> trajectoryDataList;
|
List<TrajectoryData> trajectoryDataList;
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Data
|
|
||||||
class TrajectoryData {
|
|
||||||
private Long id;
|
|
||||||
private Long sessionId;
|
|
||||||
private Long timestamp;
|
|
||||||
|
|
||||||
// 基础遥测数据
|
|
||||||
private Long rc;
|
|
||||||
private Long gps;
|
|
||||||
private Long gpsStatus;
|
|
||||||
private double voltage;
|
|
||||||
private double cellVoltage;
|
|
||||||
private Long consumption;
|
|
||||||
private double current;
|
|
||||||
private double speed;
|
|
||||||
private double airSpeed;
|
|
||||||
private double vSpeed;
|
|
||||||
private double altitude;
|
|
||||||
private double distance;
|
|
||||||
private double range;
|
|
||||||
private Long throttle;
|
|
||||||
private Long windDirection;
|
|
||||||
private double windSpeed;
|
|
||||||
private Long heading;
|
|
||||||
private double roll;
|
|
||||||
private double pitch;
|
|
||||||
private double yaw;
|
|
||||||
|
|
||||||
// 扩展数据
|
|
||||||
private double compassHeading;
|
|
||||||
private double droneLat;
|
|
||||||
private double droneLon;
|
|
||||||
private double homeLat;
|
|
||||||
private double homeLon;
|
|
||||||
private String mapType;
|
|
||||||
private Boolean showTrajectory;
|
|
||||||
private String flightMode;
|
|
||||||
private Long vehicleType;
|
|
||||||
private Long autopilotType;
|
|
||||||
private Boolean isArmed;
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,11 +1,14 @@
|
|||||||
package com.corewing.app.entity;
|
package com.corewing.app.entity;
|
||||||
|
|
||||||
import com.baomidou.mybatisplus.annotation.IdType;
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
import com.baomidou.mybatisplus.annotation.TableId;
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
import com.baomidou.mybatisplus.annotation.TableName;
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
import com.corewing.app.dto.api.TrajectoryData;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
@TableName("app_replay_session")
|
@TableName("app_replay_session")
|
||||||
@@ -14,9 +17,11 @@ public class ReplaySession {
|
|||||||
/**
|
/**
|
||||||
* id
|
* id
|
||||||
*/
|
*/
|
||||||
@TableId(value = "id", type = IdType.INPUT)
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
private Long id;
|
private Long id;
|
||||||
|
|
||||||
|
private String syncId;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户id
|
* 用户id
|
||||||
*/
|
*/
|
||||||
@@ -66,4 +71,10 @@ public class ReplaySession {
|
|||||||
* 更新时间
|
* 更新时间
|
||||||
*/
|
*/
|
||||||
private Date updatedAt;
|
private Date updatedAt;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 轨迹数据点
|
||||||
|
*/
|
||||||
|
@TableField(exist = false)
|
||||||
|
List<TrajectoryData> trajectoryDataList;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,4 +36,14 @@ public class AppReplaySessionController {
|
|||||||
return Result.isBool(replaySessionService.uploadReplaySession(uploadReplaySessionRequests));
|
return Result.isBool(replaySessionService.uploadReplaySession(uploadReplaySessionRequests));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据同步id删除数据
|
||||||
|
* @param syncId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@DeleteMapping("/deleteReplaySession/{syncId}")
|
||||||
|
public Result<Boolean> deleteReplaySession(@PathVariable String syncId) {
|
||||||
|
return Result.isBool(replaySessionService.deleteReplaySession(syncId));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,10 @@ import java.util.List;
|
|||||||
|
|
||||||
|
|
||||||
public interface ReplaySessionService extends IService<ReplaySession> {
|
public interface ReplaySessionService extends IService<ReplaySession> {
|
||||||
|
|
||||||
List<ReplaySession> getReplayList(Object loginId);
|
List<ReplaySession> getReplayList(Object loginId);
|
||||||
|
|
||||||
boolean uploadReplaySession(List<uploadReplaySessionRequest> uploadReplaySessionRequests);
|
boolean uploadReplaySession(List<uploadReplaySessionRequest> uploadReplaySessionRequests);
|
||||||
|
|
||||||
|
boolean deleteReplaySession(String syncId);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,55 +1,121 @@
|
|||||||
package com.corewing.app.service.impl;
|
package com.corewing.app.service.impl;
|
||||||
|
|
||||||
|
import cn.dev33.satoken.stp.StpUtil;
|
||||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||||
|
import com.corewing.app.dto.api.TrajectoryData;
|
||||||
import com.corewing.app.dto.api.uploadReplaySessionRequest;
|
import com.corewing.app.dto.api.uploadReplaySessionRequest;
|
||||||
import com.corewing.app.entity.ReplaySession;
|
import com.corewing.app.entity.ReplaySession;
|
||||||
import com.corewing.app.mapper.ReplaySessionMapper;
|
import com.corewing.app.mapper.ReplaySessionMapper;
|
||||||
import com.corewing.app.service.ReplaySessionService;
|
import com.corewing.app.service.ReplaySessionService;
|
||||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
import com.corewing.app.util.OSSUploadUtil;
|
||||||
|
import com.fasterxml.jackson.core.type.TypeReference;
|
||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.reflect.TypeToken;
|
||||||
import org.codehaus.jettison.json.JSONArray;
|
|
||||||
import org.codehaus.jettison.json.JSONObject;
|
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import java.io.ByteArrayInputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.InputStreamReader;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Service
|
@Service
|
||||||
public class ReplaySessionServiceImpl extends ServiceImpl<ReplaySessionMapper, ReplaySession> implements ReplaySessionService {
|
public class ReplaySessionServiceImpl extends ServiceImpl<ReplaySessionMapper, ReplaySession> implements ReplaySessionService {
|
||||||
private final Gson gson;
|
|
||||||
|
|
||||||
public ReplaySessionServiceImpl(Gson gson) {
|
@Resource
|
||||||
this.gson = gson;
|
private Gson gson;
|
||||||
}
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 获取飞行记录
|
||||||
|
* @param loginId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public List<ReplaySession> getReplayList(Object loginId) {
|
public List<ReplaySession> getReplayList(Object loginId) {
|
||||||
LambdaQueryWrapper<ReplaySession> queryWrapper = new LambdaQueryWrapper<>();
|
LambdaQueryWrapper<ReplaySession> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
queryWrapper.eq(ReplaySession::getUserId, loginId);
|
queryWrapper.eq(ReplaySession::getUserId, loginId);
|
||||||
return this.list(queryWrapper);
|
// 去oss里面下载对应的json文件流,解析到文件里面
|
||||||
|
List<ReplaySession> list = list(queryWrapper);
|
||||||
|
list.forEach(m -> {
|
||||||
|
try {
|
||||||
|
InputStream inputStream = OSSUploadUtil.downloadFileToStream(m.getOssPath());
|
||||||
|
List<TrajectoryData> dataList = new Gson().fromJson(
|
||||||
|
new InputStreamReader(inputStream, StandardCharsets.UTF_8),
|
||||||
|
new TypeToken<List<TrajectoryData>>() {}.getType() // 增加 .getType()
|
||||||
|
);
|
||||||
|
m.setTrajectoryDataList(dataList);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 同步飞行记录
|
||||||
|
* @param uploadReplaySessionRequests
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
@Transactional
|
@Transactional
|
||||||
@Override
|
@Override
|
||||||
public boolean uploadReplaySession(List<uploadReplaySessionRequest> uploadReplaySessionRequests) {
|
public boolean uploadReplaySession(List<uploadReplaySessionRequest> uploadReplaySessionRequests) {
|
||||||
uploadReplaySessionRequests.forEach(replaySessionRequest -> {
|
uploadReplaySessionRequests.forEach(replaySessionRequest -> {
|
||||||
|
|
||||||
|
// 校验是否重复
|
||||||
|
LambdaQueryWrapper<ReplaySession> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(ReplaySession::getSyncId, replaySessionRequest.getSync_id());
|
||||||
|
if (count(queryWrapper) > 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
ReplaySession replaySession = new ReplaySession();
|
ReplaySession replaySession = new ReplaySession();
|
||||||
replaySession.setId(replaySessionRequest.getId());
|
replaySession.setSyncId(replaySessionRequest.getSync_id());
|
||||||
replaySession.setName(replaySessionRequest.getName());
|
replaySession.setName(replaySessionRequest.getName());
|
||||||
replaySession.setDuration(replaySessionRequest.getDuration());
|
replaySession.setDuration(replaySessionRequest.getDuration());
|
||||||
replaySession.setStartTime(replaySessionRequest.getStartTime());
|
replaySession.setStartTime(replaySessionRequest.getStart_time());
|
||||||
replaySession.setEndTime(replaySessionRequest.getEndTime());
|
replaySession.setEndTime(replaySessionRequest.getEnd_time());
|
||||||
replaySession.setDescription(replaySessionRequest.getDescription());
|
replaySession.setDescription(replaySessionRequest.getDescription());
|
||||||
replaySession.setDataCount(replaySessionRequest.getDataCount());
|
replaySession.setDataCount(replaySessionRequest.getData_count());
|
||||||
replaySession.setCreatedAt(replaySessionRequest.getCreatedAt());
|
replaySession.setCreatedAt(replaySessionRequest.getCreated_at());
|
||||||
replaySession.setUpdatedAt(replaySessionRequest.getUpdatedAt());
|
replaySession.setUpdatedAt(replaySessionRequest.getUpdated_at());
|
||||||
saveOrUpdate(replaySession);
|
replaySession.setUserId(Long.valueOf(StpUtil.getLoginId().toString()));
|
||||||
|
|
||||||
String json = gson.toJson(replaySessionRequest.getTrajectoryDataList());
|
String json = gson.toJson(replaySessionRequest.getTrajectoryDataList());
|
||||||
System.out.println(json);
|
// 必须指定编码,避免平台默认编码问题
|
||||||
|
InputStream inputStream = new ByteArrayInputStream(
|
||||||
|
json.getBytes(StandardCharsets.UTF_8)
|
||||||
|
);
|
||||||
|
String ossPath = "trajectory/" + replaySessionRequest.getSync_id() + ".json";
|
||||||
|
OSSUploadUtil.uploadFile(inputStream, ossPath);
|
||||||
|
|
||||||
|
replaySession.setOssPath(ossPath);
|
||||||
|
save(replaySession);
|
||||||
});
|
});
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据syncId删除数据
|
||||||
|
* @param syncId
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public boolean deleteReplaySession(String syncId) {
|
||||||
|
LambdaQueryWrapper<ReplaySession> queryWrapper = new LambdaQueryWrapper<>();
|
||||||
|
queryWrapper.eq(ReplaySession::getSyncId, syncId);
|
||||||
|
ReplaySession replaySession = this.getOne(queryWrapper);
|
||||||
|
if (replaySession == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
OSSUploadUtil.deleteFile("trajectory/" + syncId + ".json");
|
||||||
|
return removeById(replaySession.getId());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,21 +2,31 @@ package com.corewing.app.util;
|
|||||||
|
|
||||||
import com.aliyun.oss.OSS;
|
import com.aliyun.oss.OSS;
|
||||||
import com.aliyun.oss.OSSClientBuilder;
|
import com.aliyun.oss.OSSClientBuilder;
|
||||||
import com.aliyun.oss.model.ObjectMetadata;
|
import com.aliyun.oss.OSSException;
|
||||||
import com.aliyun.oss.model.PutObjectRequest;
|
import com.aliyun.oss.model.*;
|
||||||
import com.aliyun.oss.model.PutObjectResult;
|
|
||||||
import org.springframework.stereotype.Component;
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
import javax.annotation.PostConstruct;
|
import javax.annotation.PostConstruct;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
@Component
|
@Component
|
||||||
public class OSSUploadUtil {
|
public class OSSUploadUtil {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户登录名称 oss@1563058769875871.onaliyun.com
|
||||||
|
* AccessKey ID LTAI5tKUhXrGxZ5Gj3exWpkG
|
||||||
|
* AccessKey Secret PaBTMp3BhcOUgLQhJWmOkhfJhTlzhV
|
||||||
|
*/
|
||||||
private static final String ENDPOINT = "oss-cn-shenzhen.aliyuncs.com"; // 地域节点
|
private static final String ENDPOINT = "oss-cn-shenzhen.aliyuncs.com"; // 地域节点
|
||||||
private static final String ACCESS_KEY_ID = "your-access-key-id"; // 替换为你的 AccessKey ID
|
private static final String ACCESS_KEY_ID = "LTAI5tKUhXrGxZ5Gj3exWpkG"; // 替换为你的 AccessKey ID
|
||||||
private static final String ACCESS_KEY_SECRET = "your-access-key-secret"; // 替换为你的 AccessKey Secret
|
private static final String ACCESS_KEY_SECRET = "PaBTMp3BhcOUgLQhJWmOkhfJhTlzhV"; // 替换为你的 AccessKey Secret
|
||||||
private static final String BUCKET_NAME = "corewing-app"; // 替换为你的 Bucket 名称
|
private static final String BUCKET_NAME = "corewing-app"; // 替换为你的 Bucket 名称
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -67,6 +77,137 @@ public class OSSUploadUtil {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 OSS 下载文件到本地路径
|
||||||
|
* @param objectName OSS 中存储的文件路径(如 "firmware/20231104/update.bin")
|
||||||
|
* @param localFilePath 本地保存路径(如 "D:/downloads/update.bin")
|
||||||
|
* @return 下载是否成功
|
||||||
|
*/
|
||||||
|
public static boolean downloadFileToLocal(String objectName, String localFilePath) {
|
||||||
|
OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||||
|
try {
|
||||||
|
// 检查文件是否存在
|
||||||
|
if (!ossClient.doesObjectExist(BUCKET_NAME, objectName)) {
|
||||||
|
throw new FileNotFoundException("OSS 文件不存在:" + objectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 下载文件到本地
|
||||||
|
ossClient.getObject(new GetObjectRequest(BUCKET_NAME, objectName), new File(localFilePath));
|
||||||
|
return true;
|
||||||
|
} catch (OSSException | FileNotFoundException e) {
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (ossClient != null) {
|
||||||
|
ossClient.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 OSS 获取文件输入流(需手动关闭流)
|
||||||
|
* @param objectName OSS 中存储的文件路径
|
||||||
|
* @return 文件输入流(使用后需调用 close() 关闭)
|
||||||
|
* @throws IOException 当文件不存在或下载失败时抛出
|
||||||
|
*/
|
||||||
|
public static InputStream downloadFileToStream(String objectName) throws IOException {
|
||||||
|
OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||||
|
try {
|
||||||
|
// 检查文件是否存在
|
||||||
|
if (!ossClient.doesObjectExist(BUCKET_NAME, objectName)) {
|
||||||
|
throw new FileNotFoundException("OSS 文件不存在:" + objectName);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 获取 OSS 文件对象并返回输入流
|
||||||
|
OSSObject ossObject = ossClient.getObject(BUCKET_NAME, objectName);
|
||||||
|
return ossObject.getObjectContent();
|
||||||
|
} catch (OSSException e) {
|
||||||
|
throw new IOException("OSS 服务异常:" + e.getMessage(), e);
|
||||||
|
} finally {
|
||||||
|
// 注意:此处不能关闭 ossClient!否则输入流会被提前关闭
|
||||||
|
// 需在调用方使用完输入流后,手动关闭 ossClient 和输入流
|
||||||
|
// (或通过 try-with-resources 自动关闭)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 从 OSS 删除单个文件
|
||||||
|
* @param objectName OSS 中存储的文件路径(如 "firmware/20231104/update.bin")
|
||||||
|
* @return 删除是否成功(文件不存在时返回 false)
|
||||||
|
*/
|
||||||
|
public static boolean deleteFile(String objectName) {
|
||||||
|
OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||||
|
try {
|
||||||
|
// 先检查文件是否存在
|
||||||
|
if (!ossClient.doesObjectExist(BUCKET_NAME, objectName)) {
|
||||||
|
System.out.println("OSS 文件不存在,删除失败:" + objectName);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 执行删除操作
|
||||||
|
ossClient.deleteObject(BUCKET_NAME, objectName);
|
||||||
|
System.out.println("OSS 文件删除成功:" + objectName);
|
||||||
|
return true;
|
||||||
|
} catch (OSSException e) {
|
||||||
|
System.err.println("OSS 服务异常,删除失败:" + e.getMessage());
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (ossClient != null) {
|
||||||
|
ossClient.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 批量删除 OSS 文件(3.17.4 版本终极兼容方案)
|
||||||
|
* 逻辑:先执行批量删除,再逐个校验文件是否存在,确认删除结果
|
||||||
|
* @param objectNames OSS 文件路径列表(如 ["firmware/update1.bin", "firmware/update2.bin"])
|
||||||
|
* @return 批量删除结果(key:文件路径,value:是否删除成功)
|
||||||
|
*/
|
||||||
|
public static Map<String, Boolean> batchDeleteFiles(List<String> objectNames) {
|
||||||
|
Map<String, Boolean> deleteResult = new HashMap<>();
|
||||||
|
if (objectNames == null || objectNames.isEmpty()) {
|
||||||
|
System.out.println("批量删除失败:文件列表为空");
|
||||||
|
return deleteResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSS ossClient = new OSSClientBuilder().build(ENDPOINT, ACCESS_KEY_ID, ACCESS_KEY_SECRET);
|
||||||
|
try {
|
||||||
|
// 第一步:执行批量删除(忽略 SDK 返回结果,只保证执行删除操作)
|
||||||
|
DeleteObjectsRequest request = new DeleteObjectsRequest(BUCKET_NAME);
|
||||||
|
request.setKeys(objectNames); // 直接传入文件路径列表
|
||||||
|
ossClient.deleteObjects(request); // 执行删除,不依赖返回结果
|
||||||
|
|
||||||
|
// 第二步:逐个校验文件是否存在,确认删除结果
|
||||||
|
for (String objectName : objectNames) {
|
||||||
|
boolean isDeleted = !ossClient.doesObjectExist(BUCKET_NAME, objectName);
|
||||||
|
deleteResult.put(objectName, isDeleted);
|
||||||
|
if (isDeleted) {
|
||||||
|
System.out.println("删除成功:" + objectName);
|
||||||
|
} else {
|
||||||
|
System.err.println("删除失败:文件仍存在 -> " + objectName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch (OSSException e) {
|
||||||
|
System.err.printf("OSS 服务异常:错误码=%s,原因=%s%n",
|
||||||
|
e.getErrorCode(), e.getErrorMessage());
|
||||||
|
// 服务异常时,所有文件标记为删除失败
|
||||||
|
objectNames.forEach(name -> deleteResult.put(name, false));
|
||||||
|
} catch (Exception e) {
|
||||||
|
System.err.println("批量删除未知异常:" + e.getMessage());
|
||||||
|
objectNames.forEach(name -> deleteResult.put(name, false));
|
||||||
|
} finally {
|
||||||
|
if (ossClient != null) {
|
||||||
|
ossClient.shutdown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return deleteResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 根据文件名获取 Content-Type
|
* 根据文件名获取 Content-Type
|
||||||
* @param fileName 文件名(如 "update.bin")
|
* @param fileName 文件名(如 "update.bin")
|
||||||
|
|||||||
Reference in New Issue
Block a user