处理用户表单和文件上传的标准做法是什么?

时间:2015-04-14 17:58:52

标签: javascript angularjs node.js file-upload express

在文本字段和文件上传字段中处理数据的标准做法是什么?

这个问题类似于I asked previously,但这个问题稍微宽泛一些。

如果我们借用用户注册帐户的示例(包括nameemail和多个文件上传字段),则表单提交后执行的操作数量为:

(1)验证所有文本字段nameemail

(2)如果验证成功,请创建用户实例并将其保存到DB中。

(3)将图像保存到磁盘

(4)更新用户实例以包含已保存图像的文件路径。

上传的文件不是很大,大约5mb或更少,因此与上传大型1GB +文件相关的问题对于这个问题来说并不是真正的问题。

根据我的阅读,有两种处理方法。

  • 一起提交所有内容。

    有几个未答复的主题: https://softwareengineering.stackexchange.com/questions/239170/how-to-parse-multipart-field-file-data-separately

    Node.js Busboy parse fields and files seperatly

    我知道在提交表单时,文本字段应该之前文件字段,这要归功于我在其他问题中的mscdex评论。

    但我还能看到其他问题:

    (a)IF文本字段的验证失败,这意味着必须在另一个表单提交中重新发送所有内容。   这可能会导致DOS攻击/带宽问题,因为恶意用户不断提交包含错误文本字段但有大量文件的表单。

  • 首次选择时提交文件,然后在表单提交时,仅上传文件哈希。

    (a)潜在的DOS攻击可能发生在恶意用户上传大量位于服务器上的图像上。即使使用独立的bash脚本在X分钟后清理/tmp文件夹,用户仍然可以在清理前的X分钟内通过不断发送文件来阻塞磁盘空间。

    (b)有一个独立的清理脚本会产生时间问题。如果合法用户不断发送未通过验证的表单,但在X分钟后,用户最终会发送正确的表单,该怎么办?到那时,即使验证通过,X分钟已经过去,图像也会被擦除。

  • 其他一些我不知道的方式

我觉得第一种方式可能更容易,因为我可以使用nginx对连接进行速率限制。由于文件在验证完成之前永远不会访问磁盘,因此/tmp中的文件不会出现任何清理问题。但是我在网上搜索过,找不到任何人真正这样做,这让我相信文件上传并不是真的这样做。

使用表单数据处理文件上传的最佳方法是什么?

2 个答案:

答案 0 :(得分:0)

最简单地提交所有内容。如果验证失败,只需中止连接和/或立即发回某种响应。这将阻止处理表单的其余部分。

答案 1 :(得分:0)

将所有内容一起提交,但我不会使用多部分表单来发送常用表单数据。

我会提交两个表单,一个用于所有文本字段,另一个用于文件。 使用AJAX提交第一个表单,控制用户尝试的次数,并在用户成功完成验证后上传文件。

常见的表格发送到服务器如下:
name=DanielSunami&email=daniel@gmail.com

多部分数据完全不同:

-----------boundary0
content-disposition: form-data; name="name"

DanielSunami
-----------boundary0
content-disposition: form-data; name="email"

daniel@gmail.com
-----------boundary0--

只是解析它已经更复杂,使用更多的时间和内存。 最新的浏览器将所有字段放在文件之前,但旧版浏览器不会。想象一下,如果你得到了这个:

-----------boundary0
content-disposition: form-data; name="name"

DanielSunami
-----------boundary0
Content-Disposition: form-data; name="img"; filename="myImg.png"

�PNG

IHDR'�;�sRGB���bKGD�������    pHYs[...]
-----------boundary0
content-disposition: form-data; name="email"

daniel@gmail.com
-----------boundary0--

为避免这种情况,我们必须将文件字段与文本字段分开:

(1)提交文本 name=DanielSunami&email=daniel@gmail.com

(2)验证所有文本字段名称,电子邮件

(3)如果验证成功,请创建用户实例并将其保存到数据库中并返回某种“OK + USERID”。答案。

(4)提交文件

-----------boundary0
Content-Disposition: form-data; name="imgUSERID"; filename="myImg.png"

�PNG

IHDR'�;�sRGB���bKGD�������    pHYs[...]
-----------boundary0--

(5)将图像保存到磁盘

(6)更新用户实例以包括已保存图像的文件路径。

有关多部分表单的更多信息:https://www.ietf.org/rfc/rfc1867.txt