服务本地文件
2024年12月18日大约 5 分钟编码开发调用服务文件
[一]背景
上传和下载文件,基本上算是一个应用系统的标配。在微服务架构下,为了方便集中管理文件的上传和下载,大多都会选择 OSS 统一对文件进行管理。
但是对于硬件资源紧张或者仅是需要简单的文件上传和下载功能的用户来说,单独搭建 OSS 又是较大资源的投入和资源的浪费。另外,即使搭建了 OSS,大多需求也只会向前端提供上传下载接口,服务内部涉及文件管理,也只能通过远程调用的方式解决,这无形中就增加了代码的复杂度以及出错的记录。
在一些应用场景下,难免会存在个别服务自身需要管理部分文件,同时又不想随时采用远程上传至其它服务的需求。为了解决这个问题,Dante Cloud 新增了基于服务本地的文件上传和下载支持。可以理解为单个服务就像单体应用一样在应用本地磁盘管理部分文件。这样即可以满足规模较小的或者服务特有的文件管理需求,又不需要集成复杂的远程文件上传下载调用。
特别是 Dante Cloud 单体版本,如果有了本地文件管理,就不需要单独再搭建 OSS。
[二]使用
[1]添加配置
在你需要使用简单文件管理的服务中,添加配置,来指定存放文件的磁盘目录
herodotus:
service:
file:
destination: D:/file-store
[2]引入操作Bean
需要在你的代码中,注入 FileTemplate
Bean,然后通过调用其中相应的方法就可以进行文件管理操作。
例如,新建一个 MyFileService
,在这个 Service 代码中注入FileTemplate
Bean,如下例所示:
@Service
public class MyFileService {
private final FileTemplate fileTemplate;
public MyFileService(FileTemplate fileTemplate) {
this.fileTemplate = fileTemplate;
}
}
提示
Dante Cloud 已经默认将 FileTemplate
注入到了所有的服务中,在自己的代码中直接注入就可以使用。如果当前的操作不满足您的需求,FileTemplate
是一个接口定义,可以按您自己的需求进行扩展。
接口 FileTemplate
支持的操作如下所示:
public interface FileTemplate {
/**
* 根据文件夹和文件名获取完整的文件路径
*
* @param directory 文件夹
* @param fileName 文件名
* @return 文件 {@link File}
*/
Path getPath(String directory, String fileName);
/**
* 根据文件名获取完整的文件路径
*
* @param fileName 文件名
* @return 文件 {@link File}
*/
default Path getPath(String fileName) {
return getPath(null, fileName);
}
/**
* 获取系统存储 Json Schema 目录
*
* @return Json Schema 目录
*/
String getJsonSchemaDirectory();
/**
* 获取系统存储证书目录
*
* @return 证书目录
*/
String getCertificateDirectory();
/**
* 删除文件
*
* @param path 文件路径
*/
void delete(Path path);
/**
* 字符串写入文件
*
* @param path 文件路径
* @param content 内容
* @return 文件路径 {@link Path}
*/
Path writeString(Path path, String content);
/**
* 写入文件
*
* @param directory 文件坐在文件夹
* @param fileName 文件名。可以是包含相对路径的文件名。
* @param content 写入的内容
* @return 文件 {@link File}
*/
default Path writeString(String directory, String fileName, String content) {
Path path = getPath(directory, fileName);
return writeString(path, content);
}
/**
* 写入文件
*
* @param fileName 文件名。可以是包含相对路径的文件名。
* @param content 写入的内容
* @return 文件 {@link File}
*/
default Path writeString(String fileName, String content) {
return writeString(null, fileName, content);
}
/**
* 写入文件流
*
* @param path 文件路径
* @return 流 {@link BufferedOutputStream}
*/
BufferedOutputStream writeOutputStream(Path path);
/**
* 写入文件 需要手动关闭流
*
* @param directory 文件坐在文件夹
* @param fileName 文件名。可以是包含相对路径的文件名。
* @return 流 {@link BufferedOutputStream}
*/
default BufferedOutputStream writeOutputStream(String directory, String fileName) {
Path path = getPath(directory, fileName);
return writeOutputStream(path);
}
/**
* 写入文件 需要手动关闭流
*
* @param fileName 文件名。可以是包含相对路径的文件名。
* @return 流 {@link BufferedOutputStream}
*/
default BufferedOutputStream writeOutputStream(String fileName) {
return writeOutputStream(null, fileName);
}
/**
* 读取文件
*
* @param path 文件路径
* @return 文件内容 {@link String}
*/
String readString(Path path);
/**
* 读取文件
*
* @param directory 文件坐在文件夹
* @param fileName 文件名。可以是包含相对路径的文件名。
* @return 文件内容 {@link String}
*/
default String readString(String directory, String fileName) {
Path path = getPath(directory, fileName);
return readString(path);
}
/**
* 读取文件
*
* @param fileName 文件名。可以是包含相对路径的文件名。
* @return 文件内容 {@link String}
*/
default String readString(String fileName) {
return readString(null, fileName);
}
/**
* 读取文件。需要手动关闭流
*
* @param path 文件路径
* @return 流 {@link BufferedInputStream}
*/
BufferedInputStream readInputStream(Path path);
/**
* 读取文件。需要手动关闭流
*
* @param directory 文件坐在文件夹
* @param fileName 文件名。可以是包含相对路径的文件名。
* @return 流 {@link BufferedInputStream}
*/
default BufferedInputStream readInputStream(String directory, String fileName) {
Path path = getPath(directory, fileName);
return readInputStream(path);
}
/**
* 读取文件。需要手动关闭流
*
* @param fileName 文件名。可以是包含相对路径的文件名。
* @return 流 {@link BufferedInputStream}
*/
default BufferedInputStream readInputStream(String fileName) {
return readInputStream(null, fileName);
}
/**
* 文件上传
*
* @param destinationUrl 上传请求地址
* @param path 文件路径
* @return 是否成功
*/
boolean upload(String destinationUrl, Path path);
/**
* 文件下载
*
* @param destinationUrl 上传请求地址
* @param path 文件路径
* @return 是否成功
*/
boolean download(String destinationUrl, Path path);
}
[三]注意事项
- 如果您的服务中包含文件操作代码,那么当前服务在部署为多实例的情况下,一定要考虑本地文件的共享问题。
- 如果您的服务中包含文件操作代码,那么服务在以 Docker 方式运行时,建议将服务本地文件存储目录,挂载映射至主机磁盘中