Firefox 4:使用 FormData 简化 JS 表单处理

此功能已添加到 Mozilla Central(主干)中,目前仅适用于 Firefox Nightly Build

XMLHttpRequest 2 级(编辑草案) 添加了对新 FormData 接口的支持。FormData 对象提供了一种简单的方法来构建一组表示表单字段及其值的键值对,然后可以使用 XMLHttpRequest send() 方法以“multipart/form-data”格式轻松发送这些键值对。

为什么使用 FormData?

当您想要从网页(文件、非 ASCII 内容)向服务器发送复杂数据时,必须使用 multipart/form-data 内容类型。要在 <form> 中设置内容类型,您需要编写

这通常是您用于上传文件的操作。

从 Firefox 3.6 开始,您可以使用 JavaScript 操作文件(请参阅 文件 API),并且您可能希望使用 XMLHttpRequest 发送文件。但是,例如,如果您想要复制此表单,这将非常困难,因为您必须在 JavaScript 中自己创建 multipart/form-data 内容(例如,请参阅 这段代码,我在一段时间前编写了它,用于实现 multipart/form-data:丑陋且速度慢)。

这就是 FormData 有用的地方:它可以再现 JavaScript 中的 <form> 提交机制

FormData 对象

FormData 对象允许您编译一组键值对,以便使用 XMLHttpRequest 发送这些键值对。此对象只有一个方法

append(key, value);

其中 key 是您的值的名称,value 可以是字符串或文件。

您可以创建一个 FormData 对象,追加值,然后通过 XMLHttpRequest 发送它。如果您想模拟前面的表单,您可以编写

// aFile could be from an input type="file" or from a Dragged'n Dropped file
var formdata = new FormData();
formdata.append("nickname", "Foooobar");
formdata.append("website", "https://hacks.mozilla.ac.cn");
formdata.append("media", aFile);
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://foo.bar/upload.php");
xhr.send(formdata);

FormData 和 <form> 元素

Firefox 对 HTML 表单元素进行了一些扩展,添加了一个 getFormData() 方法,该方法允许您将表单数据作为 FormData 对象获取。这还没有成为 HTML 标准的一部分,但预计会在将来的某个时间点添加到规范中(尽管名称可能有所不同)。

var formElement = document.getElementById("myFormElement");
var xhr = new XMLHttpRequest();
xhr.open("POST", "submitform.php");
xhr.send(formElement.getFormData());

您也可以在从表单中检索 FormData 对象并发送它之间向该对象添加数据,如下所示

var formElement = document.getElementById("myFormElement");
formData = formElement.getFormData();
formData.append("serialnumber", serialNumber++);
xhr.send(formData);

这允许您在发送表单数据之前对其进行扩展,以包括表单上不可编辑的其他信息。

资源

关于 Paul Rouget

Paul 是 Firefox 开发人员。

Paul Rouget 的更多文章…


21 条评论

  1. marcoos

    所以,如果我理解正确,这意味着使用 FormData 和最近在 Gecko 中实现的所有与文件相关的功能,我们终于可以实现一个 JS 上传进度条,而无需进行任何奇怪的 sendAsBinary() 操作,并且可以使用与普通 HTML 表单相同的后端代码。

    基本上,这使得 SWFUpload 这样的讨厌的 Flash 技巧不再需要了,太棒了!

    顺便说一下,这是这篇帖子的波兰语翻译:http://blog.marcoos.com/2010/05/17/mozilla-hacks-interfejs-formdata-wkrotce-w-firefoksie/ :)

    2010 年 5 月 17 日 下午 1:44

    1. Paul Rouget

      是的,完全正确。

      2010 年 5 月 18 日 上午 5:32

  2. Edwin Martin

    也会有 setFormData() 吗?

    2010 年 5 月 17 日 下午 3:31

  3. Brett Zamir

    只要文件是 UTF-8 格式,发送 Unicode UTF-8 数据(即非 ASCII 内容)似乎在没有 enctype=”multipart/form-data” 的情况下没有问题。我理解错了吗?

    2010 年 5 月 17 日 下午 9:38

  4. […] 原文:https://hacks.mozilla.ac.cn/2010/05/formdata-interface-coming-to-firefox/ […]

    2010 年 5 月 18 日 上午 1:02

  5. QOAL

    是否可以删除或修改数据?
    例如,通过 formData.append(key, null); 或其他方式?
    我之所以这样问,是因为肯定存在这样的情况,即您需要执行 formData = formElement.getFormData();,但随后又需要修改表单数据?

    2010 年 5 月 18 日 上午 3:06

  6. fpiat

    任何从事开发的人员都已实现了这一点。我们需要的只是 html5 规范中的第 4.10 节 表单。但是画布似乎更性感。唉。

    2010 年 5 月 18 日 上午 4:02

    1. Paul Rouget

      我们正在努力:https://wiki.mozilla.org/User:Mounir.lamouri/HTML5_Forms

      2010 年 5 月 18 日 上午 6:39

  7. pd

    这将会包含在 IE9 中吗?

    2010 年 5 月 18 日 上午 10:36

    1. Andy

      在 IE 博客中提出请求,或许会…

      2010 年 6 月 21 日 下午 3:53

  8. […] 而且我们不需要特殊的限制文件大小。将来,我们将考虑使用另一种在 Firefox 4 中受支持且使用传统方法的上传文件的高效方法...:var files = event.originalEvent.dataTransfer.files; // 拖放事件 var url = […]

    2010 年 6 月 23 日 上午 8:46

  9. AlfonsoML

    IE9 不会支持它:http://alfonsoml.blogspot.com/2010/07/formdata-interface-wont-be-available.html

    2010 年 7 月 1 日 上午 2:04

  10. […] - 我们还支持 FormData 方法,这使得从 File API 和其他来源向 […] 发送复杂数据变得更加容易。

    2010 年 7 月 6 日 下午 10:51

  11. […] 来自 Jonas Sicking,他在 Gecko 中负责处理面向内容的功能。他介绍了 FormData,我们之前已经讨论过,但他展示了它如何与我们在 Firefox 4 中添加的 File API 的重要部分连接起来:[…]

    2010 年 7 月 7 日 下午 6:58

  12. […] 相关功能上做了很多工作的 Jonas Sicking 的客座文章。他介绍了我们之前讨论过的 FormData,但他展示了它如何与我们在 Firefox 4 中添加的 File API 的 […]

    2010 年 7 月 11 日 下午 8:30

  13. kn33ch41

    我非常期待使用此方法进行异步文件上传。目前用于确保服务器将数据读取为标准帖子的方法不太好。

    我希望传言是真的,Firefox 4 能够在 11 月发布!

    2010 年 7 月 18 日 下午 5:49

  14. kn33ch41

    在开发异步文件上传脚本时,我意识到它也遵守相同域限制。但是,表单可以发布到任何地方,这是一个非常常见的需求。例如,将图像发布到指定的图像处理服务器。对于 XHR 2,是否会有一些例外情况来处理向备用域/子域发送数据?

    2010 年 7 月 18 日 下午 7:27

  15. Daniel Kirsch

    我喜欢新的表单可能性。但是,只要我需要支持不支持它的浏览器,通常简单地使用一个版本并以传统方式执行就可以了。
    我还喜欢新的 xhr.upload (nsIXMLHttpRequestUpload) 对象,它允许我为我的上传添加一个进度指示器。
    因此,如果我可以为 FORM 元素添加类似于 xhr.upload 对象的内容,那就太好了。这样,我就可以在应用程序中添加一个进度指示器,而无需创建 XMLHTTPRequest 来发送数据。
    最简单的方法是通过属性或 addEventListener 简单地向 FORM 元素添加“onprogress”监听器

    嗯,这可能不太可能,因为服务器可能已经向客户端发送了一些内容以供显示,但也许有一种方法。

    2010 年 9 月 21 日 下午 4:01

  16. Glenn Maynard

    如果其他人想知道它去了哪里,现在是“new FormData(formElement)”,虽然这似乎还没有出现在任何规范或文档中。Chrome 也以这种方式支持它。

    旧方法更好:任何 JavaScript 对象都可以实现一个 getFormData 方法来为该对象返回一个 FormData。如果我有一个可以生成其内容的 FormData 的自定义对象,它可以公开一个 getFormData 方法,提供与 HTMLFormElement 一致且兼容的接口。作为 FormData 构造函数的特例,这种自然一致性就丢失了。

    2010 年 12 月 17 日 下午 4:00

  17. André

    请告诉我,我可以从 img 标签 src 发送数据,而不是从 input 中获取文件吗?

    2012 年 11 月 25 日 下午 3:23

    1. Robert Nyman

      不,要发送数据,它需要通过表单。

      2012 年 11 月 26 日 上午 1:28

本文的评论已关闭。