Clean Architecture项目中上传文件的存放位置及访问方式咨询
Clean Architecture 项目上传文件存放方案
先给明确结论:用户上传的文件属于运行时产生的业务数据,不是分层架构里的代码资源,不要直接存放在Infrastructure层的项目目录中,具体问题逐一说明:
上传文件的正确存放位置
本质上用户上传的文件和数据库里存的业务数据属性一致,选存储位置只看业务规模,和分层没有直接绑定关系:
- 单实例部署的小型项目:可以存在Web/API项目
wwwroot下的独立uploads目录,也可以存在服务器上单独划分的非代码目录(比如/var/app/uploads、D:\app\uploads) - 多实例部署/中大型项目:直接用独立对象存储服务(本地MinIO、云厂商OSS都可以),不要存在单台服务器本地,避免多节点文件不同步的问题
为什么不推荐在Infrastructure层建assets文件夹存上传文件
Infrastructure层的职责是放外层具体实现的代码,比如存储逻辑封装、第三方服务SDK适配,是要跟着项目编译发布的代码目录:
- 后续部署如果用覆盖发布的方式,很容易把历史上传的文件冲掉
- 开发测试环境的测试文件很容易被误提交到代码仓库,导致仓库体积膨胀
- 生产环境如果给代码目录配了执行权限,上传的恶意脚本有被执行的风险
只有项目自带的、跟着版本走的固定静态资源(比如系统默认头像、内置导出模板)才适合放在Infrastructure或者Web项目的assets类目录里,用户上传的动态文件完全不适合。
按分层规则怎么访问非wwwroot目录的文件
严格遵守依赖倒置原则就行,不需要让上层感知具体存储位置:
- 在Application层先定义抽象接口,比如
IFileStoreService,封装业务需要的上传、读取、删除、获取访问地址的方法,这一层完全不关心文件是存在本地磁盘还是云存储 - 在Infrastructure层写这个接口的具体实现:
- 本地存储的实现类里,不要硬编码路径,通过配置项读取存储根目录,或者在Web项目启动时把
IWebHostEnvironment注入进去,拿到内容根路径/Web根路径拼接目录即可 - 对象存储的实现类里,直接封装对应SDK的调用逻辑
- 本地存储的实现类里,不要硬编码路径,通过配置项读取存储根目录,或者在Web项目启动时把
- 上层的业务逻辑、接口层只依赖
IFileStoreService抽象调用,完全不需要知道文件实际存在哪
如果文件存在服务器非wwwroot的目录,要对外提供访问有两种常用方案:
- 公开无权限要求的文件:在静态文件中间件里加路径映射,把指定的HTTP路由(比如
/static-files)映射到磁盘上的实际存储目录,就能直接通过URL访问,不需要把文件挪到wwwroot下 - 需要权限校验的非公开文件:写专门的文件下载接口,先校验用户权限,校验通过后从存储位置读取文件流返回给前端即可,不会暴露实际物理路径
注意:本地存储的路径一定要写在配置文件里,不要硬编码,方便不同环境切换;生产环境给上传目录开权限时务必关闭执行权限,避免恶意上传可执行文件引发安全问题。
内容的提问来源于stack exchange,提问作者arakakivl
相关产品推荐
相关产品推荐

