在asp.net web应用程序中处理用户上传文件的标准实践

9
这是我第一次构建一个网络应用程序,其唯一目的是处理用户上传的文件,我有几个问题需要解决:

  1. 是否存在安全问题需要考虑?要处理的文件本质上是文本文件,我的应用程序将逐行读取。 我应该限制文件上传扩展名或者还有其他预防措施吗?

  2. 对于已上传的文件,什么是最好的组织方式?这些文件不需要永久存储在我的应用程序中,所以我应该将它们放在一个通用的“数据”文件夹中并删除不再需要的文件吗?

  3. 我是否忽略了任何其他重要方面来构建具有类似功能的网络应用程序?

谢谢


1
如果您不需要存储文件,那么还有什么需要组织的呢?只需读取流、处理数据并且放弃即可。如果您不需要保存文件,实际上也不需要真正地保存它们。 - Jamiec
@Jamiec 我不知道你可以这样做。你是说文件在客户端被读取,然后数据被发送到服务器吗?你会怎么做呢? - Tony
1
@Tony,文件由浏览器读取并发送到服务器。如果您想在内存中读取流,然后在完成后将其丢弃即可。但是,根据您的流量情况,这可能会对服务器造成压力。将文件保存到磁盘上肯定会更慢,但在给定时间内使用的资源较少,如果出现问题,您可以延迟处理。 - xxbbcc
2个回答

6
  1. 唯一需要注意的安全问题是在将未经数据清洗以防止 SQL 注入的原始文本插入数据库时。如果没有涉及到数据库,那么就没问题了。至于扩展名,限制扩展名只是一个很差的顶级过滤器。虽然有用,但它只是表面检查文件的内容。设置文件大小限制也会有所帮助。

  2. 将文件保存到磁盘可能会在大量事务中变得昂贵,但另一方面,随着更多请求/线程的使用,它会占用更少的服务器内存。您还可以在内存中处理文件,但对于大文件,这可能会导致不利影响。考虑您正在处理的内容并选择最佳方法。

  3. 定义超时时间,以便上传的大型文件在最终太大时不会占用不必要的服务器进程。

我假设您正在使用 ASP.NET 的 FileUpload 控件。请注意,文件不会通过 postback 持久化(以防止安全漏洞),因此用户每次请求页面时都必须浏览文件。如果您有服务器端验证程序,则这很麻烦。


编辑以回答评论:

通过在内存中工作,我是指纯粹通过代码操作上传的文件,而不必先将其物理保存在服务器磁盘上。

例如,如果您正在使用 FileUpload 控件,则可以通过 Stream 对象 FileUpload.FileContent 或字节数组 FileUpload.FileBytesAPI 参考)访问用户的文件。由于这是一个流,因此您可以直接读取文件,而无需先保存它。

标记:

<asp:FileUpload ID="fileUploadControl" ToolTip="Upload a file" runat="server" />

代码后台:

If fileUploadControl.HasFile AndAlso _
   (fileUploadControl.FileName.ToLower().EndsWith(".txt") OrElse _
    fileUploadControl.ToLower().FileName.EndsWith(".dat")) Then
    SaveThisToDataBase(fileUploadControl.FileName, fileUploadControl.FileBytes)
End If

看到了吗?根本不需要保存到磁盘。 fileUploadControl.FileBytes 包含上传的数据的字节数组。

如果您想要保存到文件,那么可以使用流将其写入磁盘。


1
我的数据库查询已经参数化了,因此注入应该没有问题。这些文件相对较小,但我不熟悉您所说的内存中处理文件是什么意思。您有任何示例或参考资料可以提供链接吗? - Tony

3
我不知道我的答案是否“标准”,但是在我面临类似情况时,我做了以下事情:
  • 我限制文件扩展名为少数几种类型,这样可以更难上传恶意文件。虽然很容易规避,但至少增加了恶意用户的一道防线。

  • 我必须为IIS下存储文件的文件夹添加IUSR帐户的写入权限。此文件夹是我的应用程序根目录的子文件夹。

  • 因为我处理了大量的文件,所以我为每个月创建了一个新的子文件夹,例如Uploaded\012012Uploaded\022012等。这样做可以加快文件访问速度,因为每个文件夹中只有几百个文件。我将每个上传文件都存储在数据库中,并定期清理文件系统。这也会删除旧的空文件夹。

正如我所说,我不知道这是否是标准(或者这是否是一种真正好的实践方法),但它对我使用它的环境效果很好。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接