使用Key/Value对和FormData能够轻易地通过XMLHttpRequest指定要传递什么数据,它是一个非常强大的发送数据到服务器的方法。
基础
通常的方法是你创建一个 FormData 对象。然后你使用append方法来加入任何额外的key和他们的值。就像这样:
view source
print?
1 var form = new FormData();
2 form.append("myName", "Robert");
然后你只需使用XMLHttpRequest(XHR)的send方法来发送:
1 var xhrForm = new XMLHttpRequest();
2 xhrForm.open("POST", "getfile.php");
3 xhrForm.send(form);
对于FormData,有趣的是不限制你加入字符串,但是实际上还有许多不同的类型
• 字符串
• 数字(发送的时候会转换为字符串)
• 文件
• 二进制对象(BLOB)
要想能够在服务器端处理一个FormData的表单,要知道的重点是和一个multipart/form-data编码的常规表单一样发送。
加入文件和二进制对象(blob)
如果你想加入一个文件,最简单的方法是访问通过一个type="file"的输入元素选择的文件:
1 form.append("theFile", fileInput.files[0]);
加入一个二进制对象(blob)
在发送和接收值方面,使用二进制对象(blob)是十分强大的。一个二进制对象(blob)可以手动通过它的内容或者类型的引用去创建:
1 form.append("blobbie", new Blob([imgAsBlobRef], {"type": "image/png"}));
创建你的二进制对象(blob)的内容:
你也可以自己穿件一个二进制对象(blob)的内容:
1 var xmlForBlob = ["Robert"],
2 xmlBlob = new Blob(xmlForBlob, {"type" : "text/xml"});
3
4 form.append("xmlParts", xmlBlob);
在页面上获取图像和创建二进制对象(blob)
另外,你也可以在页面上通过XHR来获取一个图像然后通过FormData来发送:
01 // Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
02 var rhino = document.querySelector("#rhino");
03 if (rhino) {
04 var xhr = new XMLHttpRequest(),
05 blob;
06
07 xhr.open("GET", "rhino.png", true);
08 xhr.responseType = "blob";
09
10 xhr.onreadystatechange = function () {
11 if (xhr.readyState === 4 && xhr.status === 200) {
12 blob = xhr.response;
13 var form = new FormData();
14 form.append("blobbie", blob);
15
16 var xhrForm = new XMLHttpRequest();
17 xhrForm.open("POST", "getfile.php");
18 xhrForm.send(form);
19 }
20 };
21 // Send XHR
22 xhr.send();
23 }
使用Web Activity
我以前在Mozilla Hacks博客上写过一篇关于Web Activities的文章, 使用里面的方法,你可以访问设备的相机,拍照,然后得到一个二进制对象(blob)的返回结果。
一旦你获取到它(blob),你就可以把它发送到服务器。在这种情况下,我们会通关过Web Activity拍照,通过FormData发送二进制对象到服务器,然后从服务器获得返回的图像,截止在当前页面中呈现图片:
01 var pick = new MozActivity({
02 name: "pick",
03 data: {
04 type: ["image/png", "image/jpg", "image/jpeg"]
05 }
06 });
07
08 pick.onsuccess = function () {? var form = new FormData();
09 form.append("blobbie", this.result.blob);
10
11 var xhrForm = new XMLHttpRequest();
12 xhrForm.open("POST", "getfile.php");
13 xhrForm.send(form);
14
15 xhrForm.onreadystatechange = function () {
16 if (xhrForm.readyState === 4) {
17 var img = document.createElement("img");
18 img.src = xhrForm.response;
19
20 var imagePresenter = document.querySelector("#image-presenter");
21 imagePresenter.appendChild(img);
22 imagePresenter.style.display = "block";
23 }
24 };
25 };<span><span style="line-height: 19px;"> </span></span>
记得文章开头的地方我提到过的表单是在multipart/form-data的编码下发送。这里就是你怎样去读取通过FormData传送的名称、值和二进制对象的内容的方法:
1 <?php
2 $fileName = $_FILES['blobbie']['name'];
3 $fileType = $_FILES['blobbie']['type'];
4 $fileContent = file_get_contents($_FILES['blobbie']['tmp_name']);
5 $dataURL = 'data:' . $fileType . ';base64,' . base64_encode($fileContent);
6 echo $dataURL;
7 ?>
上面的代码是我在Eric Bidelman的一个gist里的发现的 。 通常,你应该能用任何的服务器端语言来做到这点。这里选择PHP,只是因为它已经在大多数服务器上运行了。
一个完整的demo
我把通过XHR获取一个在页面上的图像、通过FormData来传送它、读取内容以及返回一个图像能够再次显示在页面的URL放在了一个完整的例子中。
一般来说,这是一个展示怎样来回发送消失的实践。
可以在以下的URL中获取例子 https://github.com/robnyman/robnyman.github.com/tree/master/html5demos/formdata
(大概由于一些原因,GitHub页面不能让你运行PHP代码来读取文件内容,但是在FormData GitHub page 里可以看到带有一个不完整图像的页面/布局)。
JavaScript 代码
01 (function () {
02 // Getting a file through XMLHttpRequest as an arraybuffer and creating a Blob
03 var rhino = document.querySelector("#rhino");
04 if (rhino) {
05 var xhr = new XMLHttpRequest(),
06 blob;
07
08 xhr.open("GET", "rhino.png", true);
09 /*
10 Set the responseType to "blob".
11 If it isn't supported in the targeted web browser,
12 use "arraybuffer" instead and wrap the response
13 with new Uint8Array() below
14 */
15 xhr.responseType = "blob";
16
17 xhr.onreadystatechange = function () {
18 if (xhr.readyState === 4 && xhr.status === 200) {
19 /*
20 Create a blob from the response
21 Only needed if the responseType isn't already blob
22 If it's "arraybuffer", do this:
23
24 blob = new Blob([new Uint8Array(xhr.response)], {type: "image/png"});
25 */
26 blob = xhr.response;
27 var form = new FormData();
28 form.append("blobbie", blob);
29
30 var xhrForm = new XMLHttpRequest();
31 xhrForm.open("POST", "getfile.php");
32 xhrForm.send(form);
33
34 xhrForm.onreadystatechange = function () {
35 if (xhrForm.readyState === 4) {
36 console.log(xhrForm.response);
37 rhino.src = xhrForm.response;
38 }
39 };
40 }
41 };
42 // Send XHR
43 xhr.send();
44 }
45 })();
PHP 代码
1 <?php
2 $fileName = $_FILES['blobbie']['name'];
3 $fileType = $_FILES['blobbie']['type'];
4 $fileContent = file_get_contents($_FILES['blobbie']['tmp_name']);
5 $dataURL = 'data:' . $fileType . ';base64,' . base64_encode($fileContent);
6 echo $dataURL;
7 ?>
浏览器支持
实际上真的好棒!支持FormData的浏览器有:
•Firefox 4+
• Google Chrome 7+
• Safari 5+
• Opera 12+
• Internet Explorer 10+ (计划支持)
支持二进制对象的浏览器有:
•Firefox 13+
• Google Chrome 20+
• Safari 5.1+
• Opera 12.1+
• Internet Explorer 10+ (计划支持)