实现一个能够自动删除的临时文件
发表于|更新于
|阅读量:
背景
前段时间在弄关于文档转图片然后进行处理的工作,其中由于图片内容会多次读取,所以将其持久化在本地。
但是由于图片是临时文件,所以需要在使用完之后删除。
最初的实现是使用try-with-resource,但是随着流程变得复杂,图片的生命周期变得不可控,所以需要一个更好的解决方案。
思路
- 利用Cleaner的特性,在文件被GC回收时,进行删除操作。需要注意不要在cleaner中应用
this
对象,否则会导致内存泄漏。
- 利用MDC保存当前线程的MDC信息,这样cleaner执行时,用于跟踪上下文的MDC可以保留,使得traceId等信息不会丢失。
实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
| package com.haizhi.metis.document.parse.common;
import java.io.File; import java.io.IOException; import java.lang.ref.Cleaner; import java.nio.file.Path; import java.util.Map; import java.util.UUID;
import lombok.Getter; import lombok.extern.slf4j.Slf4j; import org.jetbrains.annotations.NotNull; import org.slf4j.MDC;
@Slf4j @Getter public class AutoCleanCacheFile extends File { private static final Cleaner cleaner = Cleaner.create(); private final static String TMP_FILE_PREFIX = "temp_"; private static final String tmpdir = System.getProperty("java.io.tmpdir"); private static final long serialVersionUID = 1L; private final String fileType; public AutoCleanCacheFile(@NotNull String fileType) { super(createTempFile(fileType)); this.fileType = fileType; Path path = toPath(); Map<String, String> mdcMap= MDC.getCopyOfContextMap(); cleaner.register(this, () -> { Map<String, String> backup = MDC.getCopyOfContextMap(); MDC.setContextMap(mdcMap); boolean delete = path.toFile().delete(); log.debug("delete temp File [{}]: {}", delete, path); if (backup != null){ MDC.setContextMap(backup); } }); } private static String createTempFile(@NotNull String fileType) { try { String path = Path.of(tmpdir, String.format("%s%s.%s", TMP_FILE_PREFIX, UUID.randomUUID(), fileType)).toString(); boolean newFile = new File(path).createNewFile(); log.debug("create temp File [{}]: {}", newFile, path); return path; } catch (IOException e) { throw new IllegalStateException(e); } }
public static AutoCleanCacheFile build(@NotNull String fileType){ return new AutoCleanCacheFile(fileType); } }
|