be: 文件真删除

This commit is contained in:
RB 2025-08-27 11:05:49 +08:00
parent f3714bf7a7
commit b9f4d6a941
2 changed files with 78 additions and 27 deletions

View file

@ -7,6 +7,7 @@ See LICENSE and COMMERCIAL in the project root for license information.
package com.rebuild.core.service.files;
import cn.devezhao.commons.CalendarUtils;
import cn.devezhao.persist4j.Field;
import cn.devezhao.persist4j.Record;
import cn.devezhao.persist4j.engine.ID;
@ -19,7 +20,6 @@ import com.rebuild.core.metadata.easymeta.DisplayType;
import com.rebuild.core.privileges.UserService;
import com.rebuild.core.service.general.OperatingContext;
import com.rebuild.core.service.general.OperatingObserver;
import com.rebuild.core.service.general.recyclebin.RecycleBinCleanerJob;
import com.rebuild.utils.JSONUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
@ -53,9 +53,9 @@ public class AttachmentAwareObserver extends OperatingObserver {
if (record.hasValue(field.getName(), false)) {
JSONArray files = parseFilesJson(record.getObjectValue(field.getName()));
for (Object file : files) {
Record add = createAttachment(
Record c = buildAttachment(
field, context.getAfterRecord().getPrimary(), (String) file, context.getOperator());
creates.add(add);
creates.add(c);
}
}
}
@ -72,8 +72,8 @@ public class AttachmentAwareObserver extends OperatingObserver {
Record before = context.getBeforeRecord();
List<Record> creates = new ArrayList<>();
List<ID> deletes = new ArrayList<>();
// 4.2 标记删除
List<Record> createsAndUpdates = new ArrayList<>();
for (Field field : fileFields) {
String fieldName = field.getName();
if (record.hasValue(fieldName)) {
@ -101,21 +101,24 @@ public class AttachmentAwareObserver extends OperatingObserver {
.setParameter(3, o)
.unique();
if (delete != null) {
deletes.add((ID) delete[0]);
Record d = EntityHelper.forUpdate((ID) delete[0], UserService.SYSTEM_USER, false);
d.setBoolean(EntityHelper.IsDeleted, true);
d.setDate(EntityHelper.ModifiedOn, CalendarUtils.now());
createsAndUpdates.add(d);
}
}
for (Object o : afterFiles) {
Record add = createAttachment(
Record c = buildAttachment(
field, context.getAfterRecord().getPrimary(), (String) o, context.getOperator());
creates.add(add);
createsAndUpdates.add(c);
}
}
}
if (creates.isEmpty() && deletes.isEmpty()) return;
if (createsAndUpdates.isEmpty()) return;
Application.getCommonsService().createOrUpdateAndDelete(
creates.toArray(new Record[0]), deletes.toArray(new ID[0]), false);
Application.getCommonsService()
.createOrUpdate(createsAndUpdates.toArray(new Record[0]), false);
}
@Override
@ -130,23 +133,17 @@ public class AttachmentAwareObserver extends OperatingObserver {
.array();
if (array.length == 0) return;
// 标记删除以便记录从回收站恢复后可用
final boolean rbEnable = RecycleBinCleanerJob.isEnableRecycleBin();
// 4.2 标记删除
List<Record> updates = new ArrayList<>();
List<ID> deletes = new ArrayList<>();
for (Object[] o : array) {
if (rbEnable) {
Record upt = EntityHelper.forUpdate((ID) o[0], UserService.SYSTEM_USER, false);
upt.setBoolean(EntityHelper.IsDeleted, true);
updates.add(upt);
} else {
deletes.add((ID) o[0]);
}
Record d = EntityHelper.forUpdate((ID) o[0], UserService.SYSTEM_USER, false);
d.setBoolean(EntityHelper.IsDeleted, true);
d.setDate(EntityHelper.ModifiedOn, CalendarUtils.now());
updates.add(d);
}
Application.getCommonsService().createOrUpdateAndDelete(
updates.toArray(new Record[0]), deletes.toArray(new ID[0]), false);
Application.getCommonsService()
.createOrUpdate(updates.toArray(new Record[0]), false);
}
private JSONArray parseFilesJson(Object files) {
@ -155,7 +152,7 @@ public class AttachmentAwareObserver extends OperatingObserver {
else return JSON.parseArray(files.toString());
}
private Record createAttachment(Field field, ID recordId, String filePath, ID user) {
private Record buildAttachment(Field field, ID recordId, String filePath, ID user) {
Record attach = FilesHelper.createAttachment(filePath, user);
attach.setInt("belongEntity", field.getOwnEntity().getEntityCode());
attach.setString("belongField", field.getName());

View file

@ -8,21 +8,27 @@ See LICENSE and COMMERCIAL in the project root for license information.
package com.rebuild.core.service.general.recyclebin;
import cn.devezhao.commons.CalendarUtils;
import cn.devezhao.commons.ObjectUtils;
import cn.devezhao.persist4j.Entity;
import cn.devezhao.persist4j.engine.ID;
import com.rebuild.core.Application;
import com.rebuild.core.metadata.EntityHelper;
import com.rebuild.core.metadata.MetadataHelper;
import com.rebuild.core.support.ConfigurationItem;
import com.rebuild.core.support.RebuildConfiguration;
import com.rebuild.core.support.distributed.DistributedJobLock;
import com.rebuild.core.support.integration.QiniuCloud;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.springframework.core.NamedThreadLocal;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
/**
* 回收站/变更历史清理
@ -40,6 +46,7 @@ public class RecycleBinCleanerJob extends DistributedJobLock {
// 回收站
final Set<String> deletePaths42 = new HashSet<>();
final int rbDays = RebuildConfiguration.getInt(ConfigurationItem.RecycleBinKeepingDays);
if (rbDays > 0) {
log.info("RecycleBin clean running ... {}d", rbDays);
@ -71,6 +78,15 @@ public class RecycleBinCleanerJob extends DistributedJobLock {
refEntity.getField(refRecordIdName).getPhysicalName(),
recordIdName, commonFrom);
dels.add(delRef);
// 4.2 删除附件
if ("Attachment".equals(refName)) {
String sql = "select FILE_PATH " + delRef.substring(7);
Object[][] array = Application.getQueryFactory().createNativeQuery(sql).array();
for (Object[] o : array) {
deletePaths42.add((String) o[0]);
}
}
}
String delSql = "delete " + commonFrom;
@ -99,15 +115,53 @@ public class RecycleBinCleanerJob extends DistributedJobLock {
log.warn("RevisionHistory cleaned : {}", del);
}
// CommonLog 保留6个月
// CommonLog 保留 180d
Entity entity = MetadataHelper.getEntity(EntityHelper.CommonsLog);
String delSql = String.format(
"delete from `%s` where `%s` < '%s 00:00:00'",
entity.getPhysicalName(),
entity.getField("logTime").getPhysicalName(),
CalendarUtils.getUTCDateFormat().format(CalendarUtils.addMonth(-6)));
CalendarUtils.getUTCDateFormat().format(CalendarUtils.addDay(-180)));
Application.getSqlExecutor().execute(delSql, 60 * 3);
// 4.2 已删除附件最少保留 180d
List<ID> deletesAuto42 = new ArrayList<>();
Object[][] array = Application.createQueryNoFilter(
"select attachmentId,filePath from Attachment where isDeleted = 'T' and modifiedOn < ?")
.setParameter(1, CalendarUtils.addDay(-Math.max(rbDays, 180)))
.array();
for (Object[] o : array) {
deletesAuto42.add((ID) o[0]);
deletePaths42.add((String) o[1]);
}
// 删记录
if (!deletesAuto42.isEmpty()) {
Application.getCommonsService().delete(deletesAuto42.toArray(new ID[0]), false);
}
// 删文件
int del = 0;
for (String path : deletePaths42) {
Object[] o = Application.createQueryNoFilter(
"select count(filePath) from Attachment where filePath = ?")
.setParameter(1, path)
.unique();
// 检查附件是否有其他字段使用例如记录转换触发器处理的
if (o != null && ObjectUtils.toInt(o[0]) > 0) continue;
if (QiniuCloud.instance().available()) {
try {
boolean s = QiniuCloud.instance().delete(path);
del += s ? 1 : 0;
} catch (Exception ignored) {}
} else {
boolean s = FileUtils.deleteQuietly(RebuildConfiguration.getFileOfData(path));
del += s ? 1 : 0;
}
}
log.warn("File/Attachment deleted : {}", del);
}
// --