refactor TempFileService, use Attachment and mongodb
This commit is contained in:
@ -131,7 +131,7 @@ public enum SettingKey {
|
|||||||
|
|
||||||
MUSIC_CONTROLLER_URI,
|
MUSIC_CONTROLLER_URI,
|
||||||
|
|
||||||
// ---------- ----------
|
// ---------- 日记 ----------
|
||||||
|
|
||||||
JOURNAL_KEY,
|
JOURNAL_KEY,
|
||||||
|
|
||||||
@ -139,7 +139,22 @@ public enum SettingKey {
|
|||||||
|
|
||||||
JOURNAL_APP_SECRET,
|
JOURNAL_APP_SECRET,
|
||||||
|
|
||||||
JOURNAL_TRAVEL,
|
// ---------- 临时文件 ----------
|
||||||
|
|
||||||
|
/** 临时文件最小缓存时间 */
|
||||||
|
TEMP_FILE_TTL_MIN,
|
||||||
|
|
||||||
|
/** 临时文件最长缓存时间 */
|
||||||
|
TEMP_FILE_TTL_MAX,
|
||||||
|
|
||||||
|
/** 临时文件默认缓存时间 */
|
||||||
|
TEMP_FILE_TTL_DEFAULT,
|
||||||
|
|
||||||
|
/** 已过期的临时文件保留时间 */
|
||||||
|
TEMP_FILE_RESIDUE_TIME,
|
||||||
|
|
||||||
|
/** 每个 IP 限制有效临时文件容量 */
|
||||||
|
TEMP_FILE_LIMIT,
|
||||||
|
|
||||||
// ---------- 系统 ----------
|
// ---------- 系统 ----------
|
||||||
|
|
||||||
|
|||||||
@ -1,26 +0,0 @@
|
|||||||
package com.imyeyu.api.modules.common.bean;
|
|
||||||
|
|
||||||
import lombok.Data;
|
|
||||||
|
|
||||||
import java.nio.file.Path;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author 夜雨
|
|
||||||
* @since 2025-09-27 01:47
|
|
||||||
*/
|
|
||||||
@Data
|
|
||||||
public class TempFileMetaData {
|
|
||||||
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
private String name;
|
|
||||||
|
|
||||||
private String originalName;
|
|
||||||
|
|
||||||
private Path path;
|
|
||||||
|
|
||||||
private Long lastAccessAt;
|
|
||||||
|
|
||||||
/** 缓存时长(毫秒) */
|
|
||||||
private Long ttl;
|
|
||||||
}
|
|
||||||
@ -5,7 +5,6 @@ import com.google.gson.reflect.TypeToken;
|
|||||||
import com.imyeyu.api.bean.CaptchaFrom;
|
import com.imyeyu.api.bean.CaptchaFrom;
|
||||||
import com.imyeyu.api.modules.common.bean.ImageType;
|
import com.imyeyu.api.modules.common.bean.ImageType;
|
||||||
import com.imyeyu.api.modules.common.bean.SettingKey;
|
import com.imyeyu.api.modules.common.bean.SettingKey;
|
||||||
import com.imyeyu.api.modules.common.bean.TempFileMetaData;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.entity.Setting;
|
import com.imyeyu.api.modules.common.entity.Setting;
|
||||||
import com.imyeyu.api.modules.common.entity.Task;
|
import com.imyeyu.api.modules.common.entity.Task;
|
||||||
@ -63,12 +62,8 @@ import java.awt.Graphics2D;
|
|||||||
import java.awt.RenderingHints;
|
import java.awt.RenderingHints;
|
||||||
import java.awt.image.BufferedImage;
|
import java.awt.image.BufferedImage;
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.ByteArrayInputStream;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.RandomAccessFile;
|
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -392,29 +387,28 @@ public class CommonController {
|
|||||||
/**
|
/**
|
||||||
* 读取临时文件
|
* 读取临时文件
|
||||||
*
|
*
|
||||||
* @param fileId
|
* @param mongoId mongoId
|
||||||
* @param req
|
* @param req 请求
|
||||||
* @param resp
|
* @param resp 返回
|
||||||
*/
|
*/
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@IgnoreGlobalReturn
|
@IgnoreGlobalReturn
|
||||||
@GetMapping("/temp/file/read/{fileId}")
|
@GetMapping("/temp/file/read/{mongoId}")
|
||||||
public void tempFileRead(@PathVariable String fileId, HttpServletRequest req, HttpServletResponse resp) {
|
public void tempFileRead(@PathVariable String mongoId, HttpServletRequest req, HttpServletResponse resp) {
|
||||||
try {
|
try {
|
||||||
File file = tempFileService.get(fileId);
|
Attachment attach = attachmentService.getByMongoId(mongoId);
|
||||||
if (TimiJava.isEmpty(file) && file.exists()) {
|
if (TimiJava.isEmpty(attach)) {
|
||||||
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Path filePath = file.toPath();
|
GridFSFile file = attachmentService.readByMongoId(attach.getMongoId());
|
||||||
resp.setContentLengthLong(Files.size(filePath));
|
GridFSDownloadStream downloadStream = gridFSBucket.openDownloadStream(file.getObjectId());
|
||||||
String mimeType = new Tika().detect(filePath);
|
GridFsResource gridFsResource = new GridFsResource(file, downloadStream);
|
||||||
if (TimiJava.isNotEmpty(mimeType)) {
|
req.setAttribute(ResourceHandler.ATTR_TYPE, ResourceHandler.Type.MONGO);
|
||||||
resp.setContentType(mimeType);
|
req.setAttribute(ResourceHandler.ATTR_VALUE, gridFsResource);
|
||||||
}
|
|
||||||
req.setAttribute(ResourceHandler.ATTR_TYPE, ResourceHandler.Type.FILE);
|
resp.setContentType(attach.getMimeType());
|
||||||
req.setAttribute(ResourceHandler.ATTR_VALUE, filePath);
|
|
||||||
resourceHandler.handleRequest(req, resp);
|
resourceHandler.handleRequest(req, resp);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
resp.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
|
||||||
@ -424,41 +418,40 @@ public class CommonController {
|
|||||||
/**
|
/**
|
||||||
* 下载临时文件
|
* 下载临时文件
|
||||||
*
|
*
|
||||||
* @param fileId
|
* @param mongoId
|
||||||
* @param resp
|
* @param resp
|
||||||
*/
|
*/
|
||||||
@AOPLog
|
@AOPLog
|
||||||
@RequestRateLimit
|
@RequestRateLimit
|
||||||
@IgnoreGlobalReturn
|
@IgnoreGlobalReturn
|
||||||
@RequestMapping("/temp/file/download/{fileId}")
|
@RequestMapping("/temp/file/download/{mongoId}")
|
||||||
public void tempFileDownload(@PathVariable String fileId, HttpServletResponse resp) {
|
public void tempFileDownload(@PathVariable String mongoId, HttpServletResponse resp) {
|
||||||
try {
|
try {
|
||||||
TempFileMetaData metadata = tempFileService.metadata(fileId);
|
Attachment attach = attachmentService.getByMongoId(mongoId);
|
||||||
File file = tempFileService.get(fileId);
|
if (TimiJava.isEmpty(attach)) {
|
||||||
if (TimiJava.isEmpty(file) && file.exists()) {
|
|
||||||
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
resp.setStatus(HttpServletResponse.SC_NOT_FOUND);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String mimeType = new Tika().detect(file);
|
resp.setContentType(attach.getMimeType());
|
||||||
resp.setContentType(mimeType);
|
resp.setHeader("Content-Disposition", Network.getFileDownloadHeader(attach.getName()));
|
||||||
resp.setHeader("Content-Disposition", Network.getFileDownloadHeader(metadata.getOriginalName()));
|
|
||||||
resp.setHeader("Accept-Ranges", "bytes");
|
resp.setHeader("Accept-Ranges", "bytes");
|
||||||
|
|
||||||
RequestRange range = TimiSpring.requestRange(file.length());
|
GridFSFile file = attachmentService.readByMongoId(mongoId);
|
||||||
|
@Cleanup
|
||||||
|
GridFSDownloadStream downloadStream = gridFSBucket.openDownloadStream(file.getObjectId());
|
||||||
|
RequestRange range = TimiSpring.requestRange(attach.getSize());
|
||||||
if (range == null) {
|
if (range == null) {
|
||||||
// 完整文件
|
// 完整文件
|
||||||
resp.setContentLengthLong(file.length());
|
resp.setContentLengthLong(attach.getSize());
|
||||||
resp.setStatus(HttpServletResponse.SC_OK);
|
resp.setStatus(HttpServletResponse.SC_OK);
|
||||||
IO.toOutputStream(resp.getOutputStream(), file);
|
IO.toOutputStream(downloadStream, resp.getOutputStream());
|
||||||
} else {
|
} else {
|
||||||
// 分片文件
|
// 分片文件
|
||||||
resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
|
||||||
resp.setHeader("Content-Range", "bytes %s-%s/%s".formatted(range.getStart(), range.getEnd(), file.length()));
|
resp.setHeader("Content-Range", "bytes %s-%s/%s".formatted(range.getStart(), range.getEnd(), attach.getSize()));
|
||||||
resp.setContentLengthLong(range.getLength());
|
resp.setContentLengthLong(range.getLength());
|
||||||
|
IO.toOutputStream(downloadStream, resp.getOutputStream(), range.getStart(), range.getEnd());
|
||||||
@Cleanup RandomAccessFile raf = new RandomAccessFile(file, "r");
|
resp.flushBuffer();
|
||||||
raf.seek(range.getStart());
|
|
||||||
IO.toOutputStream(resp.getOutputStream(), raf, range.getStart(), range.getLength());
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("download error", e);
|
log.error("download error", e);
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
package com.imyeyu.api.modules.common.entity;
|
package com.imyeyu.api.modules.common.entity;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
import com.google.gson.JsonObject;
|
||||||
|
import com.imyeyu.api.TimiServerAPI;
|
||||||
import com.imyeyu.api.bean.MultilingualHandler;
|
import com.imyeyu.api.bean.MultilingualHandler;
|
||||||
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
import com.imyeyu.java.ref.Ref;
|
import com.imyeyu.java.ref.Ref;
|
||||||
import com.imyeyu.spring.annotation.table.Transient;
|
import com.imyeyu.spring.annotation.table.Transient;
|
||||||
import com.imyeyu.spring.entity.Entity;
|
import com.imyeyu.spring.entity.Entity;
|
||||||
@ -48,14 +50,20 @@ public class Attachment extends Entity implements MultilingualHandler {
|
|||||||
/** 镜像 */
|
/** 镜像 */
|
||||||
MIRROR,
|
MIRROR,
|
||||||
|
|
||||||
|
/** 日记 */
|
||||||
JOURNAL,
|
JOURNAL,
|
||||||
|
|
||||||
|
/** 日记出行 */
|
||||||
JOURNAL_TRAVEL,
|
JOURNAL_TRAVEL,
|
||||||
|
|
||||||
|
/** 日记瞬间 */
|
||||||
JOURNAL_MOMENT,
|
JOURNAL_MOMENT,
|
||||||
|
|
||||||
/** 系统 */
|
/** 系统 */
|
||||||
SYSTEM
|
SYSTEM,
|
||||||
|
|
||||||
|
/** 临时文件 */
|
||||||
|
TEMP_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
protected BizType bizType;
|
protected BizType bizType;
|
||||||
@ -79,11 +87,20 @@ public class Attachment extends Entity implements MultilingualHandler {
|
|||||||
|
|
||||||
protected String md5;
|
protected String md5;
|
||||||
|
|
||||||
|
protected String uploaderIp;
|
||||||
|
|
||||||
|
protected Boolean isDestroyed;
|
||||||
|
|
||||||
protected Long destroyAt;
|
protected Long destroyAt;
|
||||||
|
|
||||||
@Transient
|
@Transient
|
||||||
protected InputStream inputStream;
|
protected InputStream inputStream;
|
||||||
|
|
||||||
|
public InputStream openInputStream() {
|
||||||
|
AttachmentService service = TimiServerAPI.applicationContext.getBean(AttachmentService.class);
|
||||||
|
return service.getInputStreamByMongoId(mongoId);
|
||||||
|
}
|
||||||
|
|
||||||
public void setAttachTypeValue(Enum<?> attachType) {
|
public void setAttachTypeValue(Enum<?> attachType) {
|
||||||
this.attachType = attachType.toString();
|
this.attachType = attachType.toString();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -3,6 +3,7 @@ package com.imyeyu.api.modules.common.mapper;
|
|||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.spring.bean.Page;
|
import com.imyeyu.spring.bean.Page;
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
|
import com.imyeyu.spring.mapper.RawMapper;
|
||||||
import org.apache.ibatis.annotations.Select;
|
import org.apache.ibatis.annotations.Select;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -11,10 +12,10 @@ import java.util.List;
|
|||||||
* @author 夜雨
|
* @author 夜雨
|
||||||
* @since 2023-08-15 10:22
|
* @since 2023-08-15 10:22
|
||||||
*/
|
*/
|
||||||
public interface AttachmentMapper extends BaseMapper<Attachment, Long> {
|
public interface AttachmentMapper extends BaseMapper<Attachment, Long>, RawMapper<Attachment, Long> {
|
||||||
|
|
||||||
/** 有效条件,非删除和销毁 */
|
/** 有效条件,非删除和销毁 */
|
||||||
String VALID = NOT_DELETE + " AND destroy_at IS NULL";
|
String VALID = NOT_DELETE + " AND (`destroy_at` IS NULL OR " + UNIX_TIME + " < `destroy_at`)";
|
||||||
|
|
||||||
@Select("SELECT * FROM attachment WHERE biz_type = #{bizType} AND biz_id = #{bizId} " + VALID + LIMIT_1)
|
@Select("SELECT * FROM attachment WHERE biz_type = #{bizType} AND biz_id = #{bizId} " + VALID + LIMIT_1)
|
||||||
Attachment selectByBizId(Attachment.BizType bizType, long bizId);
|
Attachment selectByBizId(Attachment.BizType bizType, long bizId);
|
||||||
@ -25,9 +26,12 @@ public interface AttachmentMapper extends BaseMapper<Attachment, Long> {
|
|||||||
@Select("SELECT * FROM attachment WHERE biz_type = #{bizType} AND biz_id = #{bizId} AND attach_type = #{attachType} " + VALID + LIMIT_1)
|
@Select("SELECT * FROM attachment WHERE biz_type = #{bizType} AND biz_id = #{bizId} AND attach_type = #{attachType} " + VALID + LIMIT_1)
|
||||||
Attachment selectByAttachType(Attachment.BizType bizType, long bizId, Enum<?> attachType);
|
Attachment selectByAttachType(Attachment.BizType bizType, long bizId, Enum<?> attachType);
|
||||||
|
|
||||||
List<Attachment> listByBizId(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypes, Page page);
|
List<Attachment> listByBizId(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypes, Page<Attachment> page);
|
||||||
|
|
||||||
long countByBizId(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypes);
|
long countByBizId(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypes);
|
||||||
|
|
||||||
List<Attachment> listByMd5s(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypes, List<String> md5s);
|
List<Attachment> listByMd5s(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypes, List<String> md5s);
|
||||||
|
|
||||||
|
@Select("SELECT * FROM attachment WHERE `is_destroyed` = FALSE AND `destroy_at` < " + UNIX_TIME)
|
||||||
|
List<Attachment> selectNeedDestroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -56,7 +56,9 @@ public interface AttachmentService extends BaseService<Attachment, Long> {
|
|||||||
*/
|
*/
|
||||||
long countByBizId(Attachment.BizType bizType, Long bizId, Enum<?> ...attachTypes);
|
long countByBizId(Attachment.BizType bizType, Long bizId, Enum<?> ...attachTypes);
|
||||||
|
|
||||||
List<Attachment> listByMd5s(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypeList, List<String> md5s) throws TimiException;
|
List<Attachment> listByMd5s(Attachment.BizType bizType, Long bizId, List<Enum<?>> attachTypeList, List<String> md5s);
|
||||||
|
|
||||||
void deleteByBizId(Attachment.BizType bizType, long bizId, Enum<?> ...attachTypes);
|
void deleteByBizId(Attachment.BizType bizType, long bizId, Enum<?> ...attachTypes);
|
||||||
|
|
||||||
|
List<Attachment> listNeedDestroy();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,12 +1,8 @@
|
|||||||
package com.imyeyu.api.modules.common.service;
|
package com.imyeyu.api.modules.common.service;
|
||||||
|
|
||||||
import com.imyeyu.api.modules.common.bean.TempFileMetaData;
|
|
||||||
import com.imyeyu.api.modules.common.vo.TempFileResponse;
|
import com.imyeyu.api.modules.common.vo.TempFileResponse;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -15,11 +11,5 @@ import java.util.List;
|
|||||||
*/
|
*/
|
||||||
public interface TempFileService {
|
public interface TempFileService {
|
||||||
|
|
||||||
List<TempFileResponse> store(List<MultipartFile> files, Long ttl) throws TimiException;
|
List<TempFileResponse> store(List<MultipartFile> files, Long ttl);
|
||||||
|
|
||||||
File get(String id) throws TimiException;
|
|
||||||
|
|
||||||
InputStream getInputStream(String id) throws TimiException;
|
|
||||||
|
|
||||||
TempFileMetaData metadata(String id) throws TimiException;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -15,6 +15,7 @@ import com.imyeyu.java.TimiJava;
|
|||||||
import com.imyeyu.java.bean.timi.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import com.imyeyu.network.Network;
|
import com.imyeyu.network.Network;
|
||||||
|
import com.imyeyu.spring.TimiSpring;
|
||||||
import com.imyeyu.spring.mapper.BaseMapper;
|
import com.imyeyu.spring.mapper.BaseMapper;
|
||||||
import com.imyeyu.spring.service.AbstractEntityService;
|
import com.imyeyu.spring.service.AbstractEntityService;
|
||||||
import com.imyeyu.utils.Time;
|
import com.imyeyu.utils.Time;
|
||||||
@ -67,13 +68,11 @@ public class AttachmentServiceImplement extends AbstractEntityService<Attachment
|
|||||||
@Override
|
@Override
|
||||||
public void create(Attachment attachment) {
|
public void create(Attachment attachment) {
|
||||||
TimiException.required(attachment.getBizType(), "not found attachment.bizType");
|
TimiException.required(attachment.getBizType(), "not found attachment.bizType");
|
||||||
TimiException.required(attachment.getBizId(), "not found attachment.bizId");
|
|
||||||
TimiException.required(attachment.getName(), "not found attachment.name");
|
TimiException.required(attachment.getName(), "not found attachment.name");
|
||||||
String mongoId = null;
|
String mongoId = null;
|
||||||
try {
|
try {
|
||||||
InputStream is = attachment.getInputStream();
|
InputStream is = attachment.getInputStream();
|
||||||
TimiException.required(is, "not found attachment.inputStream");
|
TimiException.required(is, "not found attachment.inputStream");
|
||||||
TimiException.requiredTrue(is.available() != 0, "empty attachment.inputStream");
|
|
||||||
|
|
||||||
StringBuilder mongoName = new StringBuilder(attachment.getBizType().toString());
|
StringBuilder mongoName = new StringBuilder(attachment.getBizType().toString());
|
||||||
if (TimiJava.isNotEmpty(attachment.getAttachType())) {
|
if (TimiJava.isNotEmpty(attachment.getAttachType())) {
|
||||||
@ -87,6 +86,8 @@ public class AttachmentServiceImplement extends AbstractEntityService<Attachment
|
|||||||
attachment.setSize(gridFSFile.getLength());
|
attachment.setSize(gridFSFile.getLength());
|
||||||
attachment.setMd5(IO.md5(gridFSBucket.openDownloadStream(gridFSFile.getObjectId())));
|
attachment.setMd5(IO.md5(gridFSBucket.openDownloadStream(gridFSFile.getObjectId())));
|
||||||
attachment.setMimeType(new Tika().detect(gridFSBucket.openDownloadStream(gridFSFile.getObjectId())));
|
attachment.setMimeType(new Tika().detect(gridFSBucket.openDownloadStream(gridFSFile.getObjectId())));
|
||||||
|
attachment.setUploaderIp(TimiSpring.getRequestIP());
|
||||||
|
attachment.setIsDestroyed(false);
|
||||||
if (attachment.getMimeType().startsWith("image")) {
|
if (attachment.getMimeType().startsWith("image")) {
|
||||||
BufferedImage image = ImageIO.read(gridFSBucket.openDownloadStream(gridFSFile.getObjectId()));
|
BufferedImage image = ImageIO.read(gridFSBucket.openDownloadStream(gridFSFile.getObjectId()));
|
||||||
attachment.setMetadata(TimiJava.defaultIfNull(attachment.getMetadata(), new JsonObject()));
|
attachment.setMetadata(TimiJava.defaultIfNull(attachment.getMetadata(), new JsonObject()));
|
||||||
@ -108,14 +109,17 @@ public class AttachmentServiceImplement extends AbstractEntityService<Attachment
|
|||||||
@Override
|
@Override
|
||||||
public void destroy(Long id) {
|
public void destroy(Long id) {
|
||||||
try {
|
try {
|
||||||
Attachment attachment = get(id);
|
Attachment attach = mapper.selectRaw(id);
|
||||||
gridFsTemplate.delete(Query.query(Criteria.where("_id").is(attachment.getMongoId())));
|
GridFSFile file = readByMongoId(attach.getMongoId());
|
||||||
|
if (file != null) {
|
||||||
if (!attachment.isDeleted()) {
|
gridFsTemplate.delete(Query.query(Criteria.where("_id").is(attach.getMongoId())));
|
||||||
attachment.setDeletedAt(Time.now());
|
|
||||||
}
|
}
|
||||||
attachment.setDestroyAt(Time.now());
|
if (!attach.isDeleted()) {
|
||||||
mapper.update(attachment);
|
attach.setDeletedAt(Time.now());
|
||||||
|
}
|
||||||
|
attach.setIsDestroyed(true);
|
||||||
|
attach.setDestroyAt(Time.now());
|
||||||
|
mapper.update(attach);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
log.error("delete mongo file error", e);
|
log.error("delete mongo file error", e);
|
||||||
throw new TimiException(TimiCode.ERROR).msgKey("TODO delete mongo file error");
|
throw new TimiException(TimiCode.ERROR).msgKey("TODO delete mongo file error");
|
||||||
@ -131,15 +135,13 @@ public class AttachmentServiceImplement extends AbstractEntityService<Attachment
|
|||||||
create(attachment);
|
create(attachment);
|
||||||
|
|
||||||
// 生成缩略图
|
// 生成缩略图
|
||||||
InputStream mimeStream = getInputStreamByMongoId(attachment.getMongoId());
|
InputStream mimeStream = attachment.openInputStream();
|
||||||
String mimeType = new Tika().detect(mimeStream);
|
String mimeType = new Tika().detect(mimeStream);
|
||||||
|
|
||||||
InputStream sourceStream = getInputStreamByMongoId(attachment.getMongoId());
|
InputStream sourceStream = attachment.openInputStream();
|
||||||
ByteArrayOutputStream thumbStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream thumbStream = new ByteArrayOutputStream();
|
||||||
switch (mimeType) {
|
switch (mimeType) {
|
||||||
case "image/png", "image/bmp", "image/jpeg" -> {
|
case "image/png", "image/bmp", "image/jpeg" -> Thumbnails.of(sourceStream).width(256).keepAspectRatio(true).toOutputStream(thumbStream);
|
||||||
Thumbnails.of(sourceStream).width(256).keepAspectRatio(true).toOutputStream(thumbStream);
|
|
||||||
}
|
|
||||||
case "video/mp4", "video/quicktime" -> {
|
case "video/mp4", "video/quicktime" -> {
|
||||||
log.info("capturing thumbnail: {}", attachment.getName());
|
log.info("capturing thumbnail: {}", attachment.getName());
|
||||||
long start = Time.now();
|
long start = Time.now();
|
||||||
@ -201,9 +203,9 @@ public class AttachmentServiceImplement extends AbstractEntityService<Attachment
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public GridFSFile readByMongoId(String mongoId) {
|
public GridFSFile readByMongoId(String mongoId) {
|
||||||
Attachment view = mapper.selectByMongoId(mongoId);
|
Attachment attach = mapper.selectByMongoId(mongoId);
|
||||||
TimiException.required(view, "not found attachment: %s".formatted(mongoId));
|
TimiException.required(attach, "not found attachment: %s".formatted(mongoId));
|
||||||
return gridFsTemplate.findOne(new Query(Criteria.where("_id").is(view.getMongoId())));
|
return gridFsTemplate.findOne(new Query(Criteria.where("_id").is(attach.getMongoId())));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -214,7 +216,7 @@ public class AttachmentServiceImplement extends AbstractEntityService<Attachment
|
|||||||
@Override
|
@Override
|
||||||
public byte[] readAllByMongoId(String mongoId) {
|
public byte[] readAllByMongoId(String mongoId) {
|
||||||
try {
|
try {
|
||||||
return IO.toBytes(getInputStreamByMongoId(mongoId));
|
return IO.toBytes(getByMongoId(mongoId).openInputStream());
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new TimiException(TimiCode.ERROR, "TODO 读取失败");
|
throw new TimiException(TimiCode.ERROR, "TODO 读取失败");
|
||||||
}
|
}
|
||||||
@ -249,4 +251,9 @@ public class AttachmentServiceImplement extends AbstractEntityService<Attachment
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<Attachment> listNeedDestroy() {
|
||||||
|
return mapper.selectNeedDestroy();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,38 +1,27 @@
|
|||||||
package com.imyeyu.api.modules.common.service.implement;
|
package com.imyeyu.api.modules.common.service.implement;
|
||||||
|
|
||||||
|
import com.google.gson.Gson;
|
||||||
import com.imyeyu.api.modules.common.bean.SettingKey;
|
import com.imyeyu.api.modules.common.bean.SettingKey;
|
||||||
import com.imyeyu.api.modules.common.bean.TempFileMetaData;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
import com.imyeyu.api.modules.common.service.SettingService;
|
import com.imyeyu.api.modules.common.service.SettingService;
|
||||||
import com.imyeyu.api.modules.common.service.TempFileService;
|
import com.imyeyu.api.modules.common.service.TempFileService;
|
||||||
import com.imyeyu.api.modules.common.vo.TempFileResponse;
|
import com.imyeyu.api.modules.common.vo.TempFileResponse;
|
||||||
import com.imyeyu.io.IO;
|
|
||||||
import com.imyeyu.io.IOSize;
|
import com.imyeyu.io.IOSize;
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
import com.imyeyu.network.Network;
|
|
||||||
import com.imyeyu.spring.TimiSpring;
|
import com.imyeyu.spring.TimiSpring;
|
||||||
|
import com.imyeyu.spring.bean.Page;
|
||||||
import com.imyeyu.utils.Time;
|
import com.imyeyu.utils.Time;
|
||||||
import jakarta.annotation.PostConstruct;
|
|
||||||
import lombok.RequiredArgsConstructor;
|
import lombok.RequiredArgsConstructor;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.web.multipart.MultipartFile;
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileNotFoundException;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.nio.file.Files;
|
|
||||||
import java.nio.file.Path;
|
|
||||||
import java.nio.file.Paths;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.UUID;
|
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author 夜雨
|
* @author 夜雨
|
||||||
@ -43,61 +32,58 @@ import java.util.concurrent.ConcurrentHashMap;
|
|||||||
@RequiredArgsConstructor
|
@RequiredArgsConstructor
|
||||||
public class TempFileServiceImplement implements TempFileService {
|
public class TempFileServiceImplement implements TempFileService {
|
||||||
|
|
||||||
private static final Long DEFAULT_TTL = Time.H * 6;
|
private final Gson gson;
|
||||||
private static final Long MAX_TTL = Time.D * 3;
|
|
||||||
private static final Long LIMIT = IOSize.GB * 10;
|
|
||||||
|
|
||||||
private final SettingService settingService;
|
private final SettingService settingService;
|
||||||
private final AttachmentService attachmentService;
|
private final AttachmentService attachmentService;
|
||||||
|
|
||||||
private Path storagePath;
|
|
||||||
|
|
||||||
private final Map<String, TempFileMetaData> metadataMap = new ConcurrentHashMap<>();
|
|
||||||
private final Map<String, Long> usageMap = new ConcurrentHashMap<>();
|
|
||||||
|
|
||||||
@PostConstruct
|
|
||||||
public void init() throws IOException {
|
|
||||||
storagePath = Paths.get(settingService.getAsString(SettingKey.TEMP_FILE_PATH));
|
|
||||||
IO.destroy(storagePath.toFile());
|
|
||||||
Files.createDirectories(storagePath);
|
|
||||||
}
|
|
||||||
|
|
||||||
public List<TempFileResponse> store(List<MultipartFile> files, Long ttl) throws TimiException {
|
public List<TempFileResponse> store(List<MultipartFile> files, Long ttl) throws TimiException {
|
||||||
ttl = TimiJava.defaultIfNull(ttl, DEFAULT_TTL);
|
String ttlMinStr = settingService.getAsString(SettingKey.TEMP_FILE_TTL_MIN);
|
||||||
TimiException.requiredTrue(0 < ttl && ttl <= MAX_TTL, "ttl must be between 1ms and 3 days(259200000ms)");
|
String ttlMaxStr = settingService.getAsString(SettingKey.TEMP_FILE_TTL_MAX);
|
||||||
|
String limitStr = settingService.getAsString(SettingKey.TEMP_FILE_LIMIT);
|
||||||
|
|
||||||
|
long minTTL = Time.parseToMS(ttlMinStr);
|
||||||
|
long maxTTL = Time.parseToMS(ttlMaxStr);
|
||||||
|
long defaultTTL = Time.parseToMS(settingService.getAsString(SettingKey.TEMP_FILE_TTL_DEFAULT));
|
||||||
|
long limit = IOSize.parse(limitStr);
|
||||||
|
long residueTime = Time.parseToMS(settingService.getAsString(SettingKey.TEMP_FILE_RESIDUE_TIME));
|
||||||
|
|
||||||
|
ttl = TimiJava.defaultIfNull(ttl, defaultTTL);
|
||||||
|
TimiException.requiredTrue(minTTL < ttl && ttl <= maxTTL, String.format("ttl must be between %s and %s", ttlMinStr, ttlMaxStr));
|
||||||
|
|
||||||
long newFileSize = files.stream().mapToLong(MultipartFile::getSize).sum();
|
long newFileSize = files.stream().mapToLong(MultipartFile::getSize).sum();
|
||||||
long currentUsage = usageMap.getOrDefault(TimiSpring.getRequestIP(), 0L);
|
{
|
||||||
TimiException.requiredTrue(currentUsage + newFileSize < LIMIT, "out of storage limit(10 GB)");
|
// 缓存池大小限制
|
||||||
|
Page<Attachment> page = new Page<>();
|
||||||
|
page.setIndex(0);
|
||||||
|
page.setSize(Long.MAX_VALUE);
|
||||||
|
{
|
||||||
|
Attachment example = new Attachment();
|
||||||
|
example.setUploaderIp(TimiSpring.getRequestIP());
|
||||||
|
page.setEqualsExample(example);
|
||||||
|
}
|
||||||
|
long currentUsage = attachmentService.page(page).getList().stream().mapToLong(Attachment::getSize).sum();
|
||||||
|
TimiException.requiredTrue(currentUsage + newFileSize < limit, "out of storage limit(%s)".formatted(limitStr));
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
List<TempFileResponse> result = new ArrayList<>();
|
List<TempFileResponse> result = new ArrayList<>();
|
||||||
|
|
||||||
|
long deletedAt = Time.now() + ttl;
|
||||||
|
long destroyAt = deletedAt + residueTime;
|
||||||
for (int i = 0; i < files.size(); i++) {
|
for (int i = 0; i < files.size(); i++) {
|
||||||
MultipartFile file = files.get(i);
|
MultipartFile file = files.get(i);
|
||||||
|
|
||||||
String fileId = UUID.randomUUID().toString();
|
Attachment attach = new Attachment();
|
||||||
String fileName = fileId;
|
attach.setBizType(Attachment.BizType.TEMP_FILE);
|
||||||
if (TimiJava.isNotEmpty(file.getOriginalFilename())) {
|
attach.setName(file.getOriginalFilename());
|
||||||
fileName = fileId + "." + Network.uriFileExtension(file.getOriginalFilename());
|
attach.setDeletedAt(deletedAt);
|
||||||
}
|
attach.setDestroyAt(destroyAt);
|
||||||
Path filePath = storagePath.resolve(fileName);
|
attach.setInputStream(file.getInputStream());
|
||||||
Files.copy(file.getInputStream(), filePath);
|
attachmentService.create(attach);
|
||||||
|
|
||||||
// 创建元数据
|
|
||||||
TempFileMetaData metadata = new TempFileMetaData();
|
|
||||||
metadata.setId(fileId);
|
|
||||||
metadata.setPath(filePath);
|
|
||||||
metadata.setName(fileName);
|
|
||||||
metadata.setOriginalName(file.getOriginalFilename());
|
|
||||||
metadata.setLastAccessAt(Time.now());
|
|
||||||
metadata.setTtl(ttl);
|
|
||||||
metadataMap.put(metadata.getId(), metadata);
|
|
||||||
|
|
||||||
TempFileResponse resp = new TempFileResponse();
|
TempFileResponse resp = new TempFileResponse();
|
||||||
resp.setId(metadata.getId());
|
resp.setId(attach.getMongoId());
|
||||||
resp.setExpireAt(metadata.getLastAccessAt() + ttl);
|
resp.setExpireAt(deletedAt);
|
||||||
|
|
||||||
usageMap.put(TimiSpring.getRequestIP(), currentUsage + newFileSize);
|
|
||||||
result.add(resp);
|
result.add(resp);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
@ -107,42 +93,20 @@ public class TempFileServiceImplement implements TempFileService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public File get(String id) throws TimiException {
|
|
||||||
TempFileMetaData metaData = metadataMap.get(id);
|
|
||||||
TimiException.required(metaData, "not found temp file");
|
|
||||||
metaData.setLastAccessAt(Time.now());
|
|
||||||
return metaData.getPath().toFile();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public InputStream getInputStream(String id) throws TimiException {
|
|
||||||
try {
|
|
||||||
return IO.getInputStream(get(id));
|
|
||||||
} catch (FileNotFoundException e) {
|
|
||||||
throw new TimiException(TimiCode.RESULT_NULL, "not found temp file");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public TempFileMetaData metadata(String id) throws TimiException {
|
|
||||||
return metadataMap.get(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Scheduled(fixedRate = 3600000)
|
@Scheduled(fixedRate = 3600000)
|
||||||
public void cleanup() {
|
public void cleanup() {
|
||||||
List<String> expiredIds = metadataMap.values()
|
// List<String> expiredIds = metadataMap.values()
|
||||||
.stream()
|
// .stream()
|
||||||
.filter(metadata -> metadata.getLastAccessAt() + metadata.getTtl() < Time.now())
|
// .filter(metadata -> metadata.getLastAccessAt() + metadata.getTtl() < Time.now())
|
||||||
.map(TempFileMetaData::getId)
|
// .map(TempFileMetaData::getId)
|
||||||
.toList();
|
// .toList();
|
||||||
for (int i = 0; i < expiredIds.size(); i++) {
|
// for (int i = 0; i < expiredIds.size(); i++) {
|
||||||
TempFileMetaData removed = metadataMap.remove(expiredIds.get(i));
|
// TempFileMetaData removed = metadataMap.remove(expiredIds.get(i));
|
||||||
if (TimiJava.isNotEmpty(removed)) {
|
// if (TimiJava.isNotEmpty(removed)) {
|
||||||
File file = removed.getPath().toFile();
|
// File file = removed.getPath().toFile();
|
||||||
IO.destroy(file);
|
// IO.destroy(file);
|
||||||
usageMap.computeIfPresent(TimiSpring.getRequestIP(), (ip, usage) -> usage - file.length());
|
// usageMap.computeIfPresent(TimiSpring.getRequestIP(), (ip, usage) -> usage - file.length());
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,49 @@
|
|||||||
|
package com.imyeyu.api.modules.common.task;
|
||||||
|
|
||||||
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.scheduling.annotation.EnableScheduling;
|
||||||
|
import org.springframework.scheduling.annotation.Scheduled;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 附件清除定时任务。每天凌晨 1 点执行,清除已过期但未销毁的附件
|
||||||
|
*
|
||||||
|
* @author 夜雨
|
||||||
|
* @since 2026-01-05 12:37
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Configuration
|
||||||
|
@EnableScheduling
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class AttachmentClearTask {
|
||||||
|
|
||||||
|
private final AttachmentService attachmentService;
|
||||||
|
|
||||||
|
@Scheduled(cron = "0 0 1 * * ?")
|
||||||
|
public void run() {
|
||||||
|
log.info("start clear expired attachments");
|
||||||
|
try {
|
||||||
|
List<Attachment> needDestroyList = attachmentService.listNeedDestroy();
|
||||||
|
if (needDestroyList.isEmpty()) {
|
||||||
|
log.info("nothing attachment need clear");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (Attachment attach : needDestroyList) {
|
||||||
|
try {
|
||||||
|
attachmentService.destroy(attach.getId());
|
||||||
|
log.info("clear attachment success: id[{}]", attach.getId());
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("clear attachment error: id[{}]", attach.getId(), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.info("end clear expired attachments");
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("attachment clear task error", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -4,7 +4,6 @@ import com.google.gson.Gson;
|
|||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||||
import com.imyeyu.api.modules.common.bean.MediaAttach;
|
import com.imyeyu.api.modules.common.bean.MediaAttach;
|
||||||
import com.imyeyu.api.modules.common.bean.Metadata;
|
import com.imyeyu.api.modules.common.bean.Metadata;
|
||||||
import com.imyeyu.api.modules.common.bean.TempFileMetaData;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
import com.imyeyu.api.modules.common.service.SettingService;
|
import com.imyeyu.api.modules.common.service.SettingService;
|
||||||
@ -15,7 +14,6 @@ import com.imyeyu.api.modules.journal.service.JournalService;
|
|||||||
import com.imyeyu.api.modules.journal.vo.journal.ArchiveRequest;
|
import com.imyeyu.api.modules.journal.vo.journal.ArchiveRequest;
|
||||||
import com.imyeyu.api.modules.journal.vo.journal.JournalRequest;
|
import com.imyeyu.api.modules.journal.vo.journal.JournalRequest;
|
||||||
import com.imyeyu.api.modules.journal.vo.journal.UpdateRequest;
|
import com.imyeyu.api.modules.journal.vo.journal.UpdateRequest;
|
||||||
import com.imyeyu.io.IO;
|
|
||||||
import com.imyeyu.java.TimiJava;
|
import com.imyeyu.java.TimiJava;
|
||||||
import com.imyeyu.java.bean.timi.TimiCode;
|
import com.imyeyu.java.bean.timi.TimiCode;
|
||||||
import com.imyeyu.java.bean.timi.TimiException;
|
import com.imyeyu.java.bean.timi.TimiException;
|
||||||
@ -27,7 +25,6 @@ import org.springframework.beans.BeanUtils;
|
|||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.transaction.annotation.Transactional;
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -69,14 +66,13 @@ public class JournalServiceImplement extends AbstractEntityService<Journal, Long
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < tempFileIds.length; i++) {
|
for (int i = 0; i < tempFileIds.length; i++) {
|
||||||
TempFileMetaData metadata = tempFileService.metadata(tempFileIds[i]);
|
Attachment tempFileAttach = attachmentService.getByMongoId(tempFileIds[i]);
|
||||||
File file = tempFileService.get(tempFileIds[i]);
|
|
||||||
|
|
||||||
Attachment sourceAttach = new Attachment();
|
Attachment sourceAttach = new Attachment();
|
||||||
sourceAttach.setName(metadata.getOriginalName());
|
sourceAttach.setName(tempFileAttach.getName());
|
||||||
sourceAttach.setBizType(Attachment.BizType.JOURNAL);
|
sourceAttach.setBizType(Attachment.BizType.JOURNAL);
|
||||||
sourceAttach.setBizId(journal.getId());
|
sourceAttach.setBizId(journal.getId());
|
||||||
sourceAttach.setInputStream(IO.getInputStream(file));
|
sourceAttach.setInputStream(tempFileAttach.openInputStream());
|
||||||
attachmentService.createMedia(sourceAttach);
|
attachmentService.createMedia(sourceAttach);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
@ -105,13 +101,13 @@ public class JournalServiceImplement extends AbstractEntityService<Journal, Long
|
|||||||
}
|
}
|
||||||
// 新增
|
// 新增
|
||||||
for (String tempFileId : TimiJava.defaultIfNull(request.getTempFileIds(), new String[0])) {
|
for (String tempFileId : TimiJava.defaultIfNull(request.getTempFileIds(), new String[0])) {
|
||||||
TempFileMetaData metadata = tempFileService.metadata(tempFileId);
|
Attachment tempFileAttach = attachmentService.getByMongoId(tempFileId);
|
||||||
|
|
||||||
Attachment sourceAttach = new Attachment();
|
Attachment sourceAttach = new Attachment();
|
||||||
sourceAttach.setName(metadata.getOriginalName());
|
sourceAttach.setName(tempFileAttach.getName());
|
||||||
sourceAttach.setBizType(Attachment.BizType.JOURNAL);
|
sourceAttach.setBizType(Attachment.BizType.JOURNAL);
|
||||||
sourceAttach.setBizId(journal.getId());
|
sourceAttach.setBizId(journal.getId());
|
||||||
sourceAttach.setInputStream(tempFileService.getInputStream(tempFileId));
|
sourceAttach.setInputStream(tempFileAttach.openInputStream());
|
||||||
attachmentService.createMedia(sourceAttach);
|
attachmentService.createMedia(sourceAttach);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,16 +144,15 @@ public class JournalServiceImplement extends AbstractEntityService<Journal, Long
|
|||||||
try {
|
try {
|
||||||
List<Attachment> thumbResult = new ArrayList<>();
|
List<Attachment> thumbResult = new ArrayList<>();
|
||||||
for (int i = 0; i < tempFileIds.length; i++) {
|
for (int i = 0; i < tempFileIds.length; i++) {
|
||||||
TempFileMetaData metadata = tempFileService.metadata(tempFileIds[i]);
|
Attachment tempFileAttach = attachmentService.getByMongoId(tempFileIds[i]);
|
||||||
File file = tempFileService.get(tempFileIds[i]);
|
|
||||||
|
|
||||||
Attachment sourceAttach = new Attachment();
|
Attachment sourceAttach = new Attachment();
|
||||||
sourceAttach.setName(metadata.getOriginalName());
|
sourceAttach.setName(tempFileAttach.getName());
|
||||||
sourceAttach.setBizType(Attachment.BizType.JOURNAL_MOMENT);
|
sourceAttach.setBizType(Attachment.BizType.JOURNAL_MOMENT);
|
||||||
sourceAttach.setBizId(0L);
|
sourceAttach.setBizId(0L);
|
||||||
sourceAttach.setAttachTypeValue(MediaAttach.Type.SOURCE);
|
sourceAttach.setAttachTypeValue(MediaAttach.Type.SOURCE);
|
||||||
sourceAttach.setSize(file.length());
|
sourceAttach.setSize(tempFileAttach.getSize());
|
||||||
sourceAttach.setInputStream(IO.getInputStream(file));
|
sourceAttach.setInputStream(tempFileAttach.openInputStream());
|
||||||
thumbResult.add(attachmentService.createMedia(sourceAttach));
|
thumbResult.add(attachmentService.createMedia(sourceAttach));
|
||||||
}
|
}
|
||||||
return thumbResult;
|
return thumbResult;
|
||||||
|
|||||||
@ -2,10 +2,8 @@ package com.imyeyu.api.modules.journal.service.implement;
|
|||||||
|
|
||||||
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
import com.imyeyu.api.config.dbsource.TimiServerDBConfig;
|
||||||
import com.imyeyu.api.modules.common.bean.MediaAttach;
|
import com.imyeyu.api.modules.common.bean.MediaAttach;
|
||||||
import com.imyeyu.api.modules.common.bean.TempFileMetaData;
|
|
||||||
import com.imyeyu.api.modules.common.entity.Attachment;
|
import com.imyeyu.api.modules.common.entity.Attachment;
|
||||||
import com.imyeyu.api.modules.common.service.AttachmentService;
|
import com.imyeyu.api.modules.common.service.AttachmentService;
|
||||||
import com.imyeyu.api.modules.common.service.TempFileService;
|
|
||||||
import com.imyeyu.api.modules.journal.entity.TravelLocation;
|
import com.imyeyu.api.modules.journal.entity.TravelLocation;
|
||||||
import com.imyeyu.api.modules.journal.mapper.TravelLocationMapper;
|
import com.imyeyu.api.modules.journal.mapper.TravelLocationMapper;
|
||||||
import com.imyeyu.api.modules.journal.service.TravelLocationService;
|
import com.imyeyu.api.modules.journal.service.TravelLocationService;
|
||||||
@ -36,7 +34,6 @@ import java.util.stream.Collectors;
|
|||||||
public class TravelLocationServiceImplement extends AbstractEntityService<TravelLocation, Long> implements TravelLocationService {
|
public class TravelLocationServiceImplement extends AbstractEntityService<TravelLocation, Long> implements TravelLocationService {
|
||||||
|
|
||||||
private final TravelService travelService;
|
private final TravelService travelService;
|
||||||
private final TempFileService tempFileService;
|
|
||||||
private final AttachmentService attachmentService;
|
private final AttachmentService attachmentService;
|
||||||
|
|
||||||
private final TravelLocationMapper mapper;
|
private final TravelLocationMapper mapper;
|
||||||
@ -51,13 +48,13 @@ public class TravelLocationServiceImplement extends AbstractEntityService<Travel
|
|||||||
public void create(TravelLocation travelLocation) {
|
public void create(TravelLocation travelLocation) {
|
||||||
super.create(travelLocation);
|
super.create(travelLocation);
|
||||||
for (String tempFileId : travelLocation.getTempFileIds()) {
|
for (String tempFileId : travelLocation.getTempFileIds()) {
|
||||||
TempFileMetaData metadata = tempFileService.metadata(tempFileId);
|
Attachment tempFileAttach = attachmentService.getByMongoId(tempFileId);
|
||||||
|
|
||||||
Attachment attach = new Attachment();
|
Attachment attach = new Attachment();
|
||||||
attach.setName(metadata.getOriginalName());
|
attach.setName(tempFileAttach.getName());
|
||||||
attach.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
attach.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
||||||
attach.setBizId(travelLocation.getId());
|
attach.setBizId(travelLocation.getId());
|
||||||
attach.setInputStream(tempFileService.getInputStream(tempFileId));
|
attach.setInputStream(tempFileAttach.openInputStream());
|
||||||
attachmentService.createMedia(attach);
|
attachmentService.createMedia(attach);
|
||||||
}
|
}
|
||||||
// 更新操作时间以保证排序
|
// 更新操作时间以保证排序
|
||||||
@ -83,13 +80,13 @@ public class TravelLocationServiceImplement extends AbstractEntityService<Travel
|
|||||||
}
|
}
|
||||||
// 新增
|
// 新增
|
||||||
for (String tempFileId : TimiJava.defaultIfNull(travelLocation.getTempFileIds(), new String[0])) {
|
for (String tempFileId : TimiJava.defaultIfNull(travelLocation.getTempFileIds(), new String[0])) {
|
||||||
TempFileMetaData metadata = tempFileService.metadata(tempFileId);
|
Attachment tempFileAttach = attachmentService.getByMongoId(tempFileId);
|
||||||
|
|
||||||
Attachment attach = new Attachment();
|
Attachment attach = new Attachment();
|
||||||
attach.setName(metadata.getOriginalName());
|
attach.setName(tempFileAttach.getName());
|
||||||
attach.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
attach.setBizType(Attachment.BizType.JOURNAL_TRAVEL);
|
||||||
attach.setBizId(travelLocation.getId());
|
attach.setBizId(travelLocation.getId());
|
||||||
attach.setInputStream(tempFileService.getInputStream(tempFileId));
|
attach.setInputStream(tempFileAttach.openInputStream());
|
||||||
attachmentService.createMedia(attach);
|
attachmentService.createMedia(attach);
|
||||||
}
|
}
|
||||||
// 更新操作时间以保证排序
|
// 更新操作时间以保证排序
|
||||||
|
|||||||
@ -31,7 +31,7 @@
|
|||||||
<resultMap id="listByRepositoryIdResult" type="com.imyeyu.api.modules.git.vo.release.ReleaseView" autoMapping="true">
|
<resultMap id="listByRepositoryIdResult" type="com.imyeyu.api.modules.git.vo.release.ReleaseView" autoMapping="true">
|
||||||
<id property="id" column="id" />
|
<id property="id" column="id" />
|
||||||
<!-- 关联附件 -->
|
<!-- 关联附件 -->
|
||||||
<collection property="attachmentList" ofType="com.imyeyu.api.modules.common.vo.attachment.AttachmentView">
|
<collection property="attachmentList" ofType="com.imyeyu.api.modules.common.entity.Attachment">
|
||||||
<id property="id" column="attachmentId" />
|
<id property="id" column="attachmentId" />
|
||||||
<result property="bizType" column="biz_type" />
|
<result property="bizType" column="biz_type" />
|
||||||
<result property="bizId" column="biz_id" />
|
<result property="bizId" column="biz_id" />
|
||||||
|
|||||||
Reference in New Issue
Block a user