架构:在哪里清理上传的文件名?

时间:2010-10-22 13:25:37

标签: c# architecture file-io input validation

我正在尝试更改处理上传文件的方式,然后再将其存储到磁盘。当来自非Windows操作系统的用户上传具有Windows文件名中非法字符的文件时,我们遇到了一些问题。

  1. 我的理想主义者告诉我,文件名应尽可能靠近网络层。因此,我们在整个业务逻辑和数据层中使用相同的正确文件名。 在实践中,这要求我们主动清理几个地方的文件名,然后再相信它。这是一个问题,因为它更容易出现程序员错误,除非您只有一个来自Web的文件入口点。

  2. 我看到的另一个选项是使用文件名上的卫生方法包装文件IO。这是不可能以不可见的方式进行的,因为我们有时需要在DB中存储文件名。如果文件名在存储到磁盘之前未更改,则DB将包含错误的文件名。如果对文件系统的所有调用都通过相同的文件名卫生方法,那么这也无关紧要,除非实际上您的操作部门希望通过从DB读取文件名来执行某些脚本作业来移动文件。

  3. 绕过选项二的方法是返回新文件名(如果它已被卫生设施更改)。这要求方法的用户知道这一点并正确处理它。像这样:

    public static FileStream CreateFile(string filename, out string newFileName)
    {
        newFileName = FileNameSanitiser.GetSanitisedFullPath(filename);
        return System.IO.File.Create(newFileName);
    }
    

    关于选项1,我们应该只有一个或两个文件上传端点。这会使这个选项更加可行。我认为值得投入时间,但我不确定我的经理是否同意......

2 个答案:

答案 0 :(得分:1)

如果仅通过您的网站界面上传文件(以及可能是重新下载文件),您可以使用GUID(或其他一些独特实体)重命名每个文件,然后存储新文件数据库中的名称和旧名称。

或者,您可以将文件内容存储在数据库本身中,这将完全避免Windows文件命名限制。请注意,这不一定是您想要做的事情 - 两种文件存储方法(即磁盘与数据库)都有利弊。

答案 1 :(得分:1)

我们做的很简单 - 任何上传的文件都会保存在FileSystem上,并带有系统生成的名称(我们使用GUID),然后数据库表存储生成的名称和实际名称。因此,UI将显示下载链接的实际名称,实际下载处理程序将在响应标题中使用相同的名称。