使用FormData对象
利用FormData
对象,你可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest
发送这个"表单".
你可以先创建一个空的FormData
对象,然后使用append()
方法向该对象里添加字段,如下:
<code class=" language-js"><span class="token keyword">var</span> oMyForm <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FormData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oMyForm<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"username"</span><span class="token punctuation">,</span> <span class="token string">"Groucho"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oMyForm<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"accountnum"</span><span class="token punctuation">,</span> <span class="token number">123456</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// 数字123456被立即转换成字符串"123456"</span>
<span class="token comment">// fileInputElement中已经包含了用户所选择的文件</span>
oMyForm<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"userfile"</span><span class="token punctuation">,</span> fileInputElement<span class="token punctuation">.</span>files<span class="token punctuation">[</span><span class="token number">0</span><span class="token punctuation">]</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> oFileBody <span class="token operator">=</span> <span class="token string">'<a id="a"><b id="b">hey!</b></a>'</span><span class="token punctuation">;</span> <span class="token comment">// Blob对象包含的文件内容</span>
<span class="token keyword">var</span> oBlob <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Blob</span><span class="token punctuation">(</span><span class="token punctuation">[</span>oFileBody<span class="token punctuation">]</span><span class="token punctuation">,</span> <span class="token punctuation">{</span> type<span class="token punctuation">:</span> <span class="token string">"text/xml"</span><span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oMyForm<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"webmasterfile"</span><span class="token punctuation">,</span> oBlob<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> oReq <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token string">"POST"</span><span class="token punctuation">,</span> <span class="token string">"http://foo.com/submitform.php"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>oMyForm<span class="token punctuation">)</span><span class="token punctuation">;</span></code>
注: 字段"userfile"和"webmasterfile"的值都包含了一个文件.通过
FormData.append()
方法赋给字段"accountnum"的数字被自动转换为字符(字段的值可以是一个
Blob
对象,一个
File
对象,或者一个字符串,剩下其他类型的值都会被自动转换成字符串).
在该例子中,我们创建了一个名为oMyForm的FormData
对象,该对象中包含了名为"username", "accountnum", "userfile" 以及 "webmasterfile"的字段名,然后使用XMLHttpRequest
的send()
方法把这些数据发送了出去."webmasterfile"字段的值不是一个字符串,还是一个Blob
对象.
可以用一个已有的<form>
元素来初始化FormData对象
,只需要把这个form
元素作为参数传入FormData
构造函数即可:
<code class=" language-js"><span class="token keyword">var</span> newFormData <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FormData</span><span class="token punctuation">(</span>someFormElement<span class="token punctuation">)</span><span class="token punctuation">;</span></code>
例如:
<code class=" language-js"><span class="token keyword">var</span> formElement <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"myFormElement"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> oReq <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token string">"POST"</span><span class="token punctuation">,</span> <span class="token string">"submitform.php"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span><span class="token keyword">new</span> <span class="token class-name">FormData</span><span class="token punctuation">(</span>formElement<span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span></code>
你还可以在已有表单数据的基础上,继续添加新的键值对,如下:
<code class=" language-js"><span class="token keyword">var</span> formElement <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"myFormElement"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
formData <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FormData</span><span class="token punctuation">(</span>formElement<span class="token punctuation">)</span><span class="token punctuation">;</span>
formData<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"serialnumber"</span><span class="token punctuation">,</span> serialNumber<span class="token operator">++</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>formData<span class="token punctuation">)</span><span class="token punctuation">;</span></code>
你可以通过这种方式添加一些不想让用户编辑的固定字段,然后再发送.
你还可以使用FormData
来发送二进制文件.首先在HTML中要有一个包含了文件输入框的form元素:
<code class=" language-html"><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>form</span> <span class="token attr-name">enctype</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>multipart/form-data<span class="token punctuation">"</span></span> <span class="token attr-name">method</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>post<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>fileinfo<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span>Your email address:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">autocomplete</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>on<span class="token punctuation">"</span></span> <span class="token attr-name">autofocus</span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>userid<span class="token punctuation">"</span></span> <span class="token attr-name">placeholder</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>email<span class="token punctuation">"</span></span> <span class="token attr-name">required</span> <span class="token attr-name">size</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>32<span class="token punctuation">"</span></span> <span class="token attr-name">maxlength</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>64<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>br</span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span>Custom file label:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>text<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>filelabel<span class="token punctuation">"</span></span> <span class="token attr-name">size</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>12<span class="token punctuation">"</span></span> <span class="token attr-name">maxlength</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>32<span class="token punctuation">"</span></span> <span class="token punctuation">/></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"><</span>br</span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>label</span><span class="token punctuation">></span></span>File to stash:<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>label</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>input</span> <span class="token attr-name">type</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>file<span class="token punctuation">"</span></span> <span class="token attr-name">name</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>file<span class="token punctuation">"</span></span> <span class="token attr-name">required</span> <span class="token punctuation">/></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>form</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span> <span class="token attr-name">id</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>output<span class="token punctuation">"</span></span><span class="token punctuation">></span></span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span>
<span class="token tag"><span class="token tag"><span class="token punctuation"><</span>a</span> <span class="token attr-name">href</span><span class="token attr-value"><span class="token punctuation">=</span><span class="token punctuation">"</span>javascript:sendForm()<span class="token punctuation">"</span></span><span class="token punctuation">></span></span>Stash the file!<span class="token tag"><span class="token tag"><span class="token punctuation"></</span>a</span><span class="token punctuation">></span></span></code>
然后你就可以使用下面的代码来异步的上传用户所选择的文件:
<code class=" language-js"><span class="token keyword">function</span> <span class="token function">sendForm</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">var</span> oOutput <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"output"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> oData <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FormData</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span>forms<span class="token punctuation">.</span><span class="token function">namedItem</span><span class="token punctuation">(</span><span class="token string">"fileinfo"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oData<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"CustomField"</span><span class="token punctuation">,</span> <span class="token string">"This is some extra data"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">var</span> oReq <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">XMLHttpRequest</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span><span class="token function">open</span><span class="token punctuation">(</span><span class="token string">"POST"</span><span class="token punctuation">,</span> <span class="token string">"stash.php"</span><span class="token punctuation">,</span> <span class="token keyword">true</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span>onload <span class="token operator">=</span> <span class="token keyword">function</span><span class="token punctuation">(</span>oEvent<span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span> <span class="token punctuation">(</span>oReq<span class="token punctuation">.</span>status <span class="token operator">==</span> <span class="token number">200</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
oOutput<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">"Uploaded!"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span> <span class="token keyword">else</span> <span class="token punctuation">{</span>
oOutput<span class="token punctuation">.</span>innerHTML <span class="token operator">=</span> <span class="token string">"Error "</span> <span class="token operator">+</span> oReq<span class="token punctuation">.</span>status <span class="token operator">+</span> <span class="token string">" occurred uploading your file.<br \/>"</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span><span class="token punctuation">;</span>
oReq<span class="token punctuation">.</span><span class="token function">send</span><span class="token punctuation">(</span>oData<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span></code>
你还可以不借助HTML表单,直接向FormData
对象中添加一个File
对象或者一个Blob
对象:
<code class=" language-js">data<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"myfile"</span><span class="token punctuation">,</span> myBlob<span class="token punctuation">)</span><span class="token punctuation">;</span></code>
如果FormData对象中的某个字段值是一个Blob
对象,则在发送http请求时,代表该Blob
对象所包含文件的文件名的"Content-Disposition"请求头的值在不同的浏览器下有所不同,Firefox使用了固定的字符串"blob,"而Chrome使用了一个随机字符串.
你还可以使用jQuery来发送FormData,但必须要正确的设置相关选项
:
<code class=" language-js"><span class="token keyword">var</span> fd <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">FormData</span><span class="token punctuation">(</span>document<span class="token punctuation">.</span><span class="token function">getElementById</span><span class="token punctuation">(</span><span class="token string">"fileinfo"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
fd<span class="token punctuation">.</span><span class="token function">append</span><span class="token punctuation">(</span><span class="token string">"CustomField"</span><span class="token punctuation">,</span> <span class="token string">"This is some extra data"</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
$<span class="token punctuation">.</span><span class="token function">ajax</span><span class="token punctuation">(</span><span class="token punctuation">{</span>
url<span class="token punctuation">:</span> <span class="token string">"stash.php"</span><span class="token punctuation">,</span>
type<span class="token punctuation">:</span> <span class="token string">"POST"</span><span class="token punctuation">,</span>
data<span class="token punctuation">:</span> fd<span class="token punctuation">,</span>
processData<span class="token punctuation">:</span> <span class="token keyword">false</span><span class="token punctuation">,</span> <span class="token comment">// 告诉jQuery不要去处理发送的数据</span>
contentType<span class="token punctuation">:</span> <span class="token keyword">false</span> <span class="token comment">// 告诉jQuery不要去设置Content-Type请求头</span>
<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;
</span></code><code class=" language-js"><span class="token punctuation"></span></code>
经典的多文件上传代码如下
html 页面
- <!DOCTYPE html>
- <html>
- <head>
- <meta charset="UTF-8"/>
- <title>xhr2</title>
- </head>
- <body>
- <div style="text-align:center;margin:100px">
- <input type="file" id="file" name="file" multiple="multiple">
- <button onclick="xhr2()">多文件上传</button>
- </div>
- <script>
- function xhr2(){
- var xhr = new XMLHttpRequest();//第一步
- //定义表单变量
- var file = document.getElementById('file').files;
- //console.log(file.length);
- //新建一个FormData对象
- var formData = new FormData(); //++++++++++
- //追加文件数据
- for(i=0;i<file.length;i++){
- formData.append("file["+i+"]", file[i]); //++++++++++
- }
- //formData.append("file", file[0]); //++++++++++
-
- //post方式
- xhr.open('POST', 'xhr2.php'); //第二步骤
- //发送请求
- xhr.send(formData); //第三步骤
- //ajax返回
- xhr.onreadystatechange = function(){ //第四步
- if ( xhr.readyState == 4 && xhr.status == 200 ) {
- console.log( xhr.responseText );
- }
- };
- //设置超时时间
- xhr.timeout = 100000;
- xhr.ontimeout = function(event){
- alert('请求超时!');
- }
- }
- </script>
- </body>
- </html>
php 页面
- <?php
- print_r($_FILES["file"]);
-
- for($i=0;$i<count($_FILES["file"]['name']);$i++){
- $name=$_FILES["file"]["name"][$i];
- move_uploaded_file($_FILES["file"]["tmp_name"][$i],iconv("UTF-8","gb2312",$name));
- }
-
- ?>