
CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载导读本文围绕 Orchard Core 的ITempDirectoryProvider临时文件存储抽象展开介绍它在分片上传、TUS 断点续传、部署/Recipe 导入导出等场景中的核心作用说明如何通过OrchardCore:TempDirectory:Path一项全局配置把临时文件从系统临时目录迁移到更大的共享卷如 Azure Files、AWS EFS/FSx并给出面向开发者的 API 使用方式与实现替换方法。读完本文你将掌握 Orchard Core 临时文件目录的租户隔离机制、配置落地方式以及如何在自己的功能模块中正确消费这套抽象。一、为什么需要ITempDirectoryProviderOrchard Core 在运行中需要写临时文件的场景非常多例如进行中的分片上传chunked upload——大文件被切分为多个分片跨多次请求写入同一个临时文件可断点续传的 TUS 上传——部分上传数据在完成前需要持久保存部署 / Recipe 导入导出——先落地压缩包再解压到临时目录处理站点 Setup 前写入磁盘的 Recipe 文件。这些消费者早期直接使用Path.GetTempPath()写系统临时目录。但系统临时目录的空间常常受限小型系统临时卷、容器化的临时磁盘都容易在小空间下被大量并发大文件上传填满。因此 Orchard Core 引入了ITempDirectoryProvider抽象位于OrchardCore.FileStorage命名空间让临时文件的基路径可配置操作者可以把它指向一个按工作负载规模规划好的卷——包括多实例部署下的共享网络卷这样在一台实例上开始的断点上传可以由另一台实例继续完成。源码佐证抽象只给路径不碰文件内容从 ITempDirectoryProvider.cs 可以看到这个抽象只负责分发真实本地文件系统路径调用方自己用System.IOAPI 完成实际读写接口本身不读不写文件内容GetRootDirectory()返回租户作用域的根目录按需创建CreateTempSubdirectory(string prefix null)在根目录下创建唯一命名的新子目录可选前缀GetTempFileName(string extension null)返回根目录下一个唯一的新文件路径文件本身不会创建扩展名可带或不带前导点。二、默认实现与租户隔离默认实现DefaultTempDirectoryProvider是基于文件系统的。其构造函数逻辑见 DefaultTempDirectoryProvider.cs非常清晰var basePath options.Value.Path; if (string.IsNullOrWhiteSpace(basePath)) { basePath Path.GetTempPath(); } // Scope temporary files per tenant so that tenants can neither collide with nor observe each others files. _rootPath Path.Combine(basePath, shellSettings.Name);也就是说读取TempDirectoryOptions.Path未配置时回退到Path.GetTempPath()用Path.Combine(basePath, shellSettings.Name)拼出租户隔离的根路径。目录布局临时文件一律按{Path}/{TenantName}/...布局。租户子目录由实现自动拼接操作者永远不需要自己拼。租户隔离的意义在于不同租户的临时文件互不冲突、互不可见——代码注释明确写道 tenants can neither collide with nor observe each others files。权限与回退行为在 Unix-like 系统上新建的租户目录使用仅属主权限UnixFileMode.UserRead | UserWrite | UserExecute即700与Directory.CreateTempSubdirectory()的行为一致见 DefaultTempDirectoryProvider.cs当Path未设置时回退到操作系统临时目录保持旧行为不变。这些行为都有测试覆盖。在 DefaultTempDirectoryProviderTests.cs 中可以看到GetRootDirectory_ReturnsTenantScopedPath_AndCreatesIt验证根路径为{basePath}/{TenantName}且目录被创建GetRootDirectory_OnUnix_CreatesWithOwnerOnlyPermissions验证 Unix 下的700权限DifferentTenants_GetIsolatedRoots验证不同租户得到隔离的根路径EmptyTempPath_FallsBackToSystemTempPath验证未配置时回退到Path.GetTempPath()GetTempFileName_HonorsExtension验证扩展名无论带不带前导点最终都规范为.zip这样的带点形式CreateTempSubdirectory_AppliesPrefixToDirectoryName验证前缀被拼到生成的目录名前。三、全局配置OrchardCore:TempDirectory基路径由OrchardCore:TempDirectory配置节全局控制对应 TempDirectoryOptions.cs 中的Path属性。完整配置示例{ OrchardCore: { TempDirectory: { // Base path under which tenant-scoped temporary files are stored. // When omitted, the operating system temporary directory (Path.GetTempPath()) is used. Path: /mnt/shared/temp } } }配置如何生效从注册代码见 ServiceCollectionExtensions.cs可以看到两个关键细节services.TryAddSingletonITempDirectoryProvider, DefaultTempDirectoryProvider()——它是租户级单例不是宿主级单例因为它依赖租户的ShellSettingsservices.ConfigureTempDirectoryOptions(configuration.GetSection(TempDirectory))——配置节从租户级IShellConfiguration读取TempDirectory段绑定到选项类。因此这一项设置会作用于所有临时文件消费者媒体分片上传、TUS 上传、部署与 Recipe 的导入/导出、租户 Recipe 上传等全部跟随OrchardCore:TempDirectory:Path。TUS 断点续传的例外说明需要注意一个细节可断点续传的TUS 部分上传数据存放在该位置的TusUploads子目录下。源码佐证见 DiskTusTempStore.cs——它用Path.Combine(tempDirectoryProvider.GetRootDirectory(), TusUploads)拼出存储目录因此同样遵循OrchardCore:TempDirectory:Path。四、挂载共享文件系统Azure Files、AWS EFS/FSx因为DefaultTempDirectoryProvider只使用普通的System.IO操作任何以已挂载文件系统路径形式呈现的存储都无需改代码即可工作——本地磁盘、SAN/NAS 卷、SMB 共享Azure Files、NFS 共享AWS EFS/FSx均可。在操作系统层面完成挂载后把Path设为挂载点即可。Linux / 容器SMB 挂载 Azure Filessudo mkdir -p /mnt/octemp sudo mount -t cifs //account.file.core.windows.net/share /mnt/octemp \ -o vers3.0,usernameaccount,passwordstorage-key,dir_mode0777,file_mode0777,serverino,nosharesock,actimeo30{ OrchardCore: { TempDirectory: { Path: /mnt/octemp } } }WindowsNew-SmbGlobalMapping -RemotePath \\account.file.core.windows.net\share -Credential $cred -Persistent $true -LocalPath Z:{ OrchardCore: { TempDirectory: { Path: Z:\\octemp } } }Azure App Service / Container Apps使用平台自带的 Azure Files 挂载能力App ServiceConfiguration → Path mappings → Azure Storage MountsContainer AppsAzureFile卷然后把Path设为平台挂载路径如/mounts/octemp。凭据与重连都由平台托管。重要警告必须是文件共享不能是对象存储把Path指向挂载的文件共享而不是对象存储。临时文件消费者要求真实、可随机访问的本地文件分片上传路径会执行Seek/SetLength并跨请求重新打开同一个文件参见 ChunkFileUploadService.cs 中对FileStream.Seek(contentRange.From, SeekOrigin.Begin)的使用部署导入会使用ZipFile.ExtractToDirectory和PhysicalFileProvider。Azure FilesSMB和 AWS EFS/FSx 支持这种语义Azure Blob 和 AWS S3 对象存储不支持。唯一的例外是 TUS 断点续传它可以通过OrchardCore.Media.Azure与OrchardCore.Media.AmazonS3功能中的ITusTempStore实现直接以对象存储为目标仓库中可找到 AzureBlobTusTempStore.cs 等实现。运维注意事项确保挂载点对应用运行身份可写共享卷与实例保持在同一区域以降低延迟现有清理任务如媒体模块的TemporaryFileLifetime过期清理现在会作用于配置后的路径——例如 ChunkFileUploadService.cs 中的PurgeTempDirectory()会按TemporaryFileLifetime清理超龄临时文件。五、在功能模块中消费ITempDirectoryProvider如果你的功能需要写临时文件请注入ITempDirectoryProvider而不是直接调用Path.GetTempPath()。这样你的临时文件会自动落入配置好的、租户隔离的位置。API 速查表成员用途GetRootDirectory()租户作用域根目录按需创建。作为需要目录的工具的基础例如TemporaryFileBuilder。GetTempFileName(extension)唯一的文件路径不会创建文件用于写单个临时文件。扩展名可选带或不带前导点均可。CreateTempSubdirectory(prefix)新建的唯一子目录——用于解压归档或通过PhysicalFileProvider暴露。可选前缀会拼到生成名称前。完整示例导入服务using OrchardCore.FileStorage; public sealed class MyImportService { private readonly ITempDirectoryProvider _tempDirectoryProvider; public MyImportService(ITempDirectoryProvider tempDirectoryProvider) _tempDirectoryProvider tempDirectoryProvider; public async Task ImportAsync(IFormFile package, CancellationToken cancellationToken) { // A unique file path under {Path}/{TenantName}/ to save the upload. var archivePath _tempDirectoryProvider.GetTempFileName(Path.GetExtension(package.FileName)); // A dedicated directory to extract into. var extractPath _tempDirectoryProvider.CreateTempSubdirectory(); try { await using (var stream File.Create(archivePath)) { await package.CopyToAsync(stream, cancellationToken); } ZipFile.ExtractToDirectory(archivePath, extractPath); // ... process the extracted files ... } finally { File.Delete(archivePath); Directory.Delete(extractPath, recursive: true); } } }记住两点只管路径清理自理store 只负责给出路径文件的创建、写入和清理完全由调用方负责。用完即删store 不会替你跟踪或过期清理。临时 ≠ 安全ITempDirectoryProvider只提供临时存储它不扫描上传内容。当临时文件来自用户上传时在永久落盘之前仍应经过FileCreationService的安全检查详见上传安全文档 file-upload-security.md。六、替换默认实现DefaultTempDirectoryProvider以TryAddSingleton方式按租户注册见 ServiceCollectionExtensions.cs因此模块可以用自己的实现替换services.Replace(ServiceDescriptor.SingletonITempDirectoryProvider, MyTempDirectoryProvider());任何替代实现都必须遵守同一契约返回真实本地文件系统路径支持随机访问与目录枚举。这正是仓库中没有 Azure Blob 或 AWS S3 版ITempDirectoryProvider的原因——对象存储无法满足消费者依赖的“基于路径、可随机访问”的契约。要把临时存储搬到云上正确做法是挂载文件共享Azure Files、AWS EFS/FSx并配置Path即本文第四节所述方案。七、小结与检查清单ITempDirectoryProvider是 Orchard Core 统一管理临时文件的入口一份OrchardCore:TempDirectory:Path配置即可把分片上传、TUS 上传、部署/Recipe 导入导出等全部临时文件消费者迁移到大容量或共享卷同时天然获得按租户的目录隔离。落地时请对照以下清单在生产环境显式配置OrchardCore:TempDirectory:Path避免依赖空间受限的系统临时目录多实例部署时优先使用共享文件系统Azure Files / AWS EFS/FSx实现跨实例断点续传确认挂载点对应用运行身份可写、与实例同区域确认消费者要求的Seek/SetLength、ZipFile.ExtractToDirectory、PhysicalFileProvider语义得到满足文件共享可以对象存储不行自研功能一律注入ITempDirectoryProvider不要直接调Path.GetTempPath()用完删除临时文件上传文件在落盘前仍要走FileCreationService安全检查。参考文件速览本文原始依据temporary-file-storage.md抽象接口ITempDirectoryProvider.cs默认实现DefaultTempDirectoryProvider.cs配置选项TempDirectoryOptions.cs注册与绑定ServiceCollectionExtensions.cs分片上传消费者ChunkFileUploadService.csTUS 磁盘存储DiskTusTempStore.cs单元测试DefaultTempDirectoryProviderTests.cs上传安全检查file-upload-security.md赞分享CMS后端Web框架【免费下载链接】OrchardCoreOrchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.项目地址https://gitcode.com/gh_mirrors/or/OrchardCore点击查看免费下载相关推荐ArchiveBox 存储架构与配置指南本地与远程文件系统选型、Rclone 挂载及 Docker 卷插件实战ArchiveBox 存储架构与配置指南本地与远程文件系统选型、Rclone 挂载及 Docker 卷插件实战 ArchiveBox 是一个开源的自托管网页存后端数据工程第50章一剑斩金丹第50章一剑斩金丹 开头: 金丹长老嘲讽林天不自量力 发展: 林天拔剑展示剑意 高潮: 一剑斩杀金丹长老全场震惊 结尾: 宗主现身有趣我要收你为亲传人工智能AI 应用AI 写作RAGAI 插件AI 技能三分钟打造专业音乐播放器foobar2000终极美化指南三分钟打造专业音乐播放器foobar2000终极美化指南 还在为foobar2000单调的界面而烦恼吗 foobox美化方案 为你提供了一站式解决方案让这桌面应用音视频上一篇音乐下载神器MusicDownload 让你的音乐收藏更简单下一篇DDT4All汽车诊断工具从入门到精通的完整指南创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考