根据我们系统托管的环境,它将使用不同的"文件系统"来管理用户上传的文件。 例如,在我们的开发环境中,我们使用Windows文件系统,但在生产环境中我们使用Azure blob存储。
使用提供程序模型,我创建了以下接口:
public interface IFileRepositoryProvider
{
void SaveFile(string fileName, Stream fileStream);
void DeleteFile(string fileName);
bool Exists(string fileName);
Stream GetStream(string fileName);
}
- 如何保存/删除/等文件的详细信息完全封装在
IFileRepositoryProvider
的具体实现中。 - Azure Blob 存储存在一些限制。 我不一定能为文件提供直接的"URI",就像我们托管在 Web 服务器上的某个虚拟目录中一样。 出于这个原因,我决定完全使用流。 由客户端代码根据需要处理流。
问题:
FileStream
或MemoryStream
会更好吗?- 将文件公开为字节数组有什么好处吗?
- 你能看到这种方法有什么严重的缺点吗?
无论您使用FileStream还是MemoryStream或其他流类型都无关紧要;您的接口应该只接受 Stream,然后可以处理各种不同的输入。
我会说流比字节数组更灵活。但是,需要注意的一件事是,在将它们传递给接口之前,您通常必须记住在流上设置 position=0。
还应考虑异步以及是否要处理正确的流式处理 - 即写入 Azure Blob 存储,同时仍从客户端接收数据(这对于 Azure 存储 API 的工作方式可能有点棘手(。
我要说的一件事是,你的界面看起来像是你试图使 Azure blob 存储的行为像文件系统,重点是文件名。Azure Blob 存储中对可以调用文件的内容存在某些限制;本质上,您的"名称"需要 URI 编码。我发现更好的方法是接受 Azure blob 存储有效地处理标识符的想法,然后尝试在文件系统上模拟该标识符。因此,当您"保存"文件时,您将传入一个名称和一个流,并将返回一个字符串,该字符串是一个标识符(它实际上是一个 URI 或 URI 的一部分(。客户端必须存储该标识符,并且在想要检索文件时必须提供该标识符。
这样做的另一个好处是,你的实现负责生成标识符,因此可以在标识符中包含 Guid 以避免任何名称冲突。
最后,如果计划在 Azure Blob 存储中存储大量文件,则应注意浏览速度较慢,几乎无法搜索。因此,为了简化支持,请仔细考虑如何构建标识符。虽然从技术上讲,Blob 存储是平面的,但可以通过在标识符中包含"/"来模拟文件夹结构。因此,例如,您可以创建一个标识符,例如年份 + "/" + 月份 + "/" + 日 + "/" + guid + '/' + Uri.Encode(文件名(。或者,您可以在标识符中包含一些特定于上下文的信息。