|
|
|
@ -15,6 +15,7 @@ import org.springframework.util.StreamUtils; |
|
|
|
import java.io.FileOutputStream; |
|
|
|
import java.io.IOException; |
|
|
|
import java.io.InputStream; |
|
|
|
import java.nio.file.FileAlreadyExistsException; |
|
|
|
import java.nio.file.Files; |
|
|
|
import java.nio.file.Path; |
|
|
|
import java.nio.file.Paths; |
|
|
|
@ -33,7 +34,7 @@ import java.util.concurrent.locks.ReentrantLock; |
|
|
|
public class CommonCameraService { |
|
|
|
/** 摄像机抓图失败时写入的兜底图片路径。 */ |
|
|
|
static final String IMAGE_CAPTURE_FAILED = "images\\imageCaptureFailed.jpg"; |
|
|
|
/** 抓图保存根目录,由当前操作系统和运行目录决定。 */ |
|
|
|
/** 抓图保存根目录,可由 INSPECT_NVR_CAPTURE_DIR 指定。 */ |
|
|
|
public static final String FILE_DIR = determineCaptureDirectory(); |
|
|
|
/** 厂商 SDK 抓图失败时的默认最大重试次数。 */ |
|
|
|
static final int DEFAULT_MAX_RETRIES = 10; |
|
|
|
@ -201,8 +202,10 @@ public class CommonCameraService { |
|
|
|
Path getFullPath(String flag, String ip, int channel) { |
|
|
|
String timeStr = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss_SSS")); |
|
|
|
String fileName = flag + "_" + ip + "_" + channel + "_" + timeStr + ".jpg"; |
|
|
|
String saveDir = FILE_DIR + LocalDate.now(); |
|
|
|
Path fullPath = Paths.get(saveDir, fileName).toAbsolutePath(); |
|
|
|
Path fullPath = Paths.get(FILE_DIR) |
|
|
|
.resolve(LocalDate.now().toString()) |
|
|
|
.resolve(fileName) |
|
|
|
.toAbsolutePath(); |
|
|
|
ensureDirectoryExists(fullPath.getParent()); |
|
|
|
return fullPath; |
|
|
|
} |
|
|
|
@ -212,16 +215,47 @@ public class CommonCameraService { |
|
|
|
* 注意路径避免包含中文,否则可能会导致文件保存失败或乱码 |
|
|
|
*/ |
|
|
|
private static String determineCaptureDirectory() { |
|
|
|
String os = System.getProperty("os.name").toLowerCase(); |
|
|
|
log.info("当前操作系统: {}", os); |
|
|
|
String userDir = System.getProperty("user.dir"); |
|
|
|
log.info("userDir: {}", userDir); |
|
|
|
String configuredDirectory = System.getenv("INSPECT_NVR_CAPTURE_DIR"); |
|
|
|
if (configuredDirectory == null || configuredDirectory.trim().isEmpty()) { |
|
|
|
configuredDirectory = System.getProperty("inspect.nvr.capture-dir"); |
|
|
|
} |
|
|
|
|
|
|
|
if (os.contains("win")) { |
|
|
|
return "D:/captures/"; |
|
|
|
Path preferredDirectory; |
|
|
|
if (configuredDirectory != null && !configuredDirectory.trim().isEmpty()) { |
|
|
|
preferredDirectory = Paths.get(configuredDirectory.trim()).toAbsolutePath(); |
|
|
|
} else if (System.getProperty("os.name", "").toLowerCase().contains("win")) { |
|
|
|
preferredDirectory = Paths.get("D:/captures").toAbsolutePath(); |
|
|
|
} else { |
|
|
|
// Linux/Unix/Mac 系统使用项目同级目录 |
|
|
|
return userDir + "/captures/"; |
|
|
|
preferredDirectory = Paths.get(System.getProperty("user.dir"), "captures").toAbsolutePath(); |
|
|
|
} |
|
|
|
|
|
|
|
try { |
|
|
|
ensureWritableDirectory(preferredDirectory); |
|
|
|
log.info("抓图目录已就绪: {}", preferredDirectory); |
|
|
|
return preferredDirectory.toString() + java.io.File.separator; |
|
|
|
} catch (IOException primaryFailure) { |
|
|
|
Path fallbackDirectory = Paths.get(System.getProperty("java.io.tmpdir"), "inspect-nvr-captures") |
|
|
|
.toAbsolutePath(); |
|
|
|
try { |
|
|
|
ensureWritableDirectory(fallbackDirectory); |
|
|
|
log.warn("抓图目录 {} 不可写,已回退到 {}:{}", |
|
|
|
preferredDirectory, fallbackDirectory, primaryFailure.toString()); |
|
|
|
return fallbackDirectory.toString() + java.io.File.separator; |
|
|
|
} catch (IOException fallbackFailure) { |
|
|
|
fallbackFailure.addSuppressed(primaryFailure); |
|
|
|
throw new IllegalStateException("抓图目录不可写,主目录=" + preferredDirectory |
|
|
|
+ ",临时目录=" + fallbackDirectory, fallbackFailure); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
/** 创建目录并通过真实文件写入确认运行用户拥有写权限。 */ |
|
|
|
private static void ensureWritableDirectory(Path directory) throws IOException { |
|
|
|
Files.createDirectories(directory); |
|
|
|
if (!Files.isDirectory(directory)) { |
|
|
|
throw new FileAlreadyExistsException(directory.toString(), null, "目标路径不是目录"); |
|
|
|
} |
|
|
|
Path probe = Files.createTempFile(directory, ".inspect-nvr-write-check-", ".tmp"); |
|
|
|
Files.delete(probe); |
|
|
|
} |
|
|
|
} |