✨ 接入账单 OSS 存储并区分生产测试目录
This commit is contained in:
@@ -5,10 +5,8 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.math.BigDecimal;
|
||||
import java.nio.file.AtomicMoveNotSupportedException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.text.SimpleDateFormat;
|
||||
@@ -85,7 +83,7 @@ import com.bms.common.exception.ServiceException;
|
||||
import com.bms.common.utils.DateUtils;
|
||||
import com.bms.common.utils.StringUtils;
|
||||
import com.bms.common.utils.file.FileUtils;
|
||||
import com.bms.common.utils.file.FileUploadUtils;
|
||||
import com.bms.common.utils.file.OssStorage;
|
||||
import com.bms.common.utils.uuid.IdUtils;
|
||||
import com.bms.price.domain.PrcIncomeBill;
|
||||
import com.bms.price.domain.PrcIncomeBillFee;
|
||||
@@ -103,6 +101,9 @@ import com.bms.price.mapper.PrcOrderBillMapper;
|
||||
*/
|
||||
@Service
|
||||
public class ArBillServiceImpl implements IArBillService {
|
||||
@Autowired
|
||||
private OssStorage ossStorage;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(ArBillServiceImpl.class);
|
||||
private static final String EXPORT_TEMPLATE_BUSINESS_TYPE = "AR_BILL";
|
||||
private static final String EXPORT_TEMPLATE_RESOURCE = "templates/ar/ar_bill_template.xlsx";
|
||||
@@ -1038,7 +1039,7 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
}
|
||||
|
||||
/**
|
||||
* 执行异步导出任务:读取模板、流式拼接明细并原子移动临时文件。
|
||||
* 执行异步导出任务:流式生成临时 Excel,上传 OSS 后才标记成功。
|
||||
*/
|
||||
@Override
|
||||
public void processExportTask(Long exportId) {
|
||||
@@ -1052,6 +1053,7 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
long startedAt = System.nanoTime();
|
||||
log.info("开始执行应收账单导出任务,exportId={}, arBillId={}", exportId, export.getArBillId());
|
||||
ArBill bill = null;
|
||||
Path temp = null;
|
||||
try {
|
||||
bill = billMapper.selectArBillById(export.getArBillId());
|
||||
if (bill == null) {
|
||||
@@ -1060,28 +1062,17 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
if (ArBillStatus.is(bill.getStatus(), ArBillStatus.DRAFT) || ArBillStatus.is(bill.getStatus(), ArBillStatus.VOID)) {
|
||||
throw new ServiceException("草稿或作废账单不可导出");
|
||||
}
|
||||
String relative = "ar/" + DateUtils.datePath() + "/" + IdUtils.fastSimpleUUID() + ".xlsx";
|
||||
String downloadDir = BmsConfig.getProfile() + File.separator + "download";
|
||||
File file = FileUploadUtils.getAbsoluteFile(downloadDir, relative);
|
||||
Path target = file.toPath();
|
||||
Path temp = Files.createTempFile(target.getParent(), ".ar-bill-export-", ".xlsx.tmp");
|
||||
boolean moved = false;
|
||||
try {
|
||||
ArExportTemplate template = resolveExportTemplate(export, bill);
|
||||
writeOoxmlWorkbook(bill, template, temp);
|
||||
moveToTarget(temp, target);
|
||||
moved = true;
|
||||
} finally {
|
||||
if (!moved) {
|
||||
Files.deleteIfExists(temp);
|
||||
}
|
||||
}
|
||||
export.setStorageKey(FileUploadUtils.getPathFileName(downloadDir, relative));
|
||||
export.setFileSize(Files.size(target));
|
||||
export.setFileHash(sha256(target));
|
||||
String objectKey = "ar/bill/" + DateUtils.datePath() + "/" + IdUtils.fastSimpleUUID() + ".xlsx";
|
||||
temp = Files.createTempFile("ar-bill-export-", ".xlsx");
|
||||
ArExportTemplate template = resolveExportTemplate(export, bill);
|
||||
writeOoxmlWorkbook(bill, template, temp);
|
||||
export.setFileSize(Files.size(temp));
|
||||
export.setFileHash(sha256(temp));
|
||||
export.setStorageKey(ossStorage.upload(temp, objectKey,
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"));
|
||||
int updated = exportMapper.markSuccess(export);
|
||||
if (updated == 0) {
|
||||
Files.deleteIfExists(target);
|
||||
ossStorage.delete(export.getStorageKey());
|
||||
log.warn("应收账单导出文件已生成但任务状态未更新,exportId={}, arBillId={}",
|
||||
exportId, export.getArBillId());
|
||||
} else {
|
||||
@@ -1097,6 +1088,14 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
logService.recordFailure(export.getArBillId(), ArLogObjectType.EXPORT, String.valueOf(exportId),
|
||||
ArLogOperationType.EXPORT, bill == null ? null : bill.getStatus(), message, export.getExportBy(), null);
|
||||
}
|
||||
} finally {
|
||||
if (temp != null) {
|
||||
try {
|
||||
Files.deleteIfExists(temp);
|
||||
} catch (IOException e) {
|
||||
log.warn("应收账单导出临时文件清理失败,exportId={}", exportId, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1127,12 +1126,17 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
throw new ServiceException("导出文件不存在或尚未生成成功");
|
||||
}
|
||||
String resource = export.getStorageKey();
|
||||
if (!FileUtils.checkAllowDownload(resource)) {
|
||||
boolean ossFile = resource.startsWith("oss://");
|
||||
if (!ossFile && !FileUtils.checkAllowDownload(resource)) {
|
||||
throw new ServiceException("导出文件路径非法");
|
||||
}
|
||||
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
|
||||
FileUtils.setAttachmentResponseHeader(response, export.getFileName());
|
||||
FileUtils.writeBytes(BmsConfig.getProfile() + FileUtils.stripPrefix(resource), response.getOutputStream());
|
||||
if (ossFile) {
|
||||
ossStorage.download(resource, response.getOutputStream());
|
||||
} else {
|
||||
FileUtils.writeBytes(BmsConfig.getProfile() + FileUtils.stripPrefix(resource), response.getOutputStream());
|
||||
}
|
||||
log.debug("应收账单导出文件下载完成,exportId={}, fileSize={}, costMs={}",
|
||||
exportId, export.getFileSize(), elapsedMillis(startedAt));
|
||||
}
|
||||
@@ -1800,14 +1804,6 @@ public class ArBillServiceImpl implements IArBillService {
|
||||
}
|
||||
}
|
||||
|
||||
private void moveToTarget(Path source, Path target) throws IOException {
|
||||
try {
|
||||
Files.move(source, target, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||
} catch (AtomicMoveNotSupportedException e) {
|
||||
Files.move(source, target, StandardCopyOption.REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
|
||||
private String exportRemark(ArBillDetail detail) {
|
||||
return StringUtils.isEmpty(detail.getRemark()) ? detail.getGoodsDescription() : detail.getRemark();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user