aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/api/xmlhttprequest/sending_and_receiving_binary_data/index.html
blob: fc7da39cfd4091066c539a82651857f4177125f8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
---
title: 发送和接收二进制数据
slug: Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
tags:
  - AJAX
  - FileReader
  - MIME
  - XMLHttpRequest
translation_of: Web/API/XMLHttpRequest/Sending_and_Receiving_Binary_Data
---
<h2 id="使用JavaScript类型数组接受二进制数据">使用JavaScript类型数组接受二进制数据</h2>

<p>可以通过设置一个XMLHttpRequest对象的 <code>responseType</code>属性来改变一个从服务器上返回的响应的数据类型.可用的属性值为空字符串 (默认), "arraybuffer", "blob", "document","json" 和 "text". <code>response属性的值会根据</code><code>responseType属性包含实体主体(entity body)</code>, 它可能会是一个 <code>ArrayBuffer</code>, <code>Blob</code>, <code>Document</code>,<code>JSON</code>, string,或者为<code>NULL(如果请求未完成或失败)</code></p>

<p>下例读取了一个二进制图像文件,并且由该文件的二进制原生字节创建了一个8位无符号整数的数组.注意,这不会解码图像,但会读取像素。 你需要一个png解码库(<a href="https://github.com/devongovett/png.js/">png decoding library</a>)。</p>

<pre class="brush: js notranslate">var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "arraybuffer";

oReq.onload = function (oEvent) {
  var arrayBuffer = oReq.response; // 注意:不是oReq.responseText
  if (arrayBuffer) {
    var byteArray = new Uint8Array(arrayBuffer);
    for (var i = 0; i &lt; byteArray.byteLength; i++) {
      // 对数组中的每个字节进行操作
    }
  }
};

oReq.send(null);
</pre>

<p>也可以通过给responseType属性设置为<code>“blob”</code>,将二进制文件读取为{{domxref("Blob")}}类型的数据。</p>

<pre class="brush: js notranslate">var oReq = new XMLHttpRequest();
oReq.open("GET", "/myfile.png", true);
oReq.responseType = "blob";

oReq.onload = function(oEvent) {
  var blob = oReq.response;
  // ...
};

oReq.send();</pre>

<h2 id="在老的浏览器中接受二进制数据">在老的浏览器中接受二进制数据</h2>

<p>下面的<code>load_binary_resource()方法</code>可以从指定的URL那里加载二进制数据,并将数据返回给调用者.</p>

<pre class="brush: js notranslate">function load_binary_resource(url) {
  var req = new XMLHttpRequest();
  req.open('GET', url, false);
  //XHR binary charset opt by Marcus Granado 2006 [http://mgran.blogspot.com]
  req.overrideMimeType('text/plain; charset=x-user-defined');
  req.send(null);
  if (req.status != 200) return '';
  return req.responseText;
}
</pre>

<p>最为奇妙的操作在第五行,该行重写了默认的MIME类型,强制浏览器将该响应当成纯文本文件来对待, 使用一个用户自定义的字符集.这样就是告诉了浏览器,不要去解析数据,直接返回未处理过的字节码.</p>

<pre class="brush: js notranslate">var filestream = load_binary_resource(url);
var abyte = filestream.charCodeAt(x) &amp; 0xff; // 扔掉的高位字节(f7)
</pre>

<p>上例从请求回来的二进制数据中得到偏移量为x处的字节.有效的偏移量范围是0到<code>filestream.length-1</code>.</p>

<p>查看 <a class="external" href="http://web.archive.org/web/20071103070418/http://mgran.blogspot.com/2006/08/downloading-binary-streams-with.html">使用XMLHttpRequest下载文件</a> 了解详情,查看<a href="/zh-cn/Code_snippets/Downloading_Files" title="zh-cn/Code_snippets/Downloading_Files">下载文件</a>.</p>

<h2 id="发送二进制数据">发送二进制数据</h2>

<p>XMLHttpRequest对象的<code>send方法</code>已被增强,可以通过简单的传入一个<a href="/zh-cn/JavaScript_typed_arrays/ArrayBuffer" title="ArrayBuffer"><code>ArrayBuffer</code></a>, {{ domxref("Blob") }}, 或者 {{ domxref("File") }}对象来发送二进制数据.</p>

<p>下例创建了一个文本文件,并使用<code>POST方法将该文件发送到了服务器上</code>.你也可以使用文本文件之外的其他二进制数据类型.</p>

<pre class="brush: js notranslate">var oReq = new XMLHttpRequest();
oReq.open("POST", url, true);
oReq.onload = function (oEvent) {
  // 上传完成后.
};

var bb = new BlobBuilder(); // 需要合适的前缀: window.MozBlobBuilder 或者 window.WebKitBlobBuilder
bb.append('abc123');

oReq.send(bb.getBlob('text/plain'));
</pre>

<h2 id="将类型数组作为二进制数据发送">将类型数组作为二进制数据发送</h2>

<p>你可以将JavaScript类型数组作为二进制数据发送出去.</p>

<pre class="brush: js notranslate">var myArray = new ArrayBuffer(512);
var longInt8View = new Uint8Array(myArray);

for (var i=0; i&lt; longInt8View.length; i++) {
  longInt8View[i] = i % 255;
}

var xhr = new XMLHttpRequest;
xhr.open("POST", url, false);
xhr.send(myArray);
</pre>

<p>上例新建了一个512字节的8比特整数的数组并发送它,当然,你也可以发送任意的二进制数据.</p>

<div class="note"><strong>注意:</strong> 从Gecko 9.0 {{ geckoRelease("9.0") }}开始,添加了使用XMLHttpRequest发送 <a href="/zh-cn/JavaScript_typed_arrays/ArrayBuffer" title="ArrayBuffer"><code>ArrayBuffer</code></a>对象的功能.</div>

<h2 id="Submitting_forms_and_uploading_files" name="Submitting_forms_and_uploading_files">提交表单和上传文件</h2>

<p>请阅读<a href="/zh-CN/docs/DOM/XMLHttpRequest/Using_XMLHttpRequest#Submitting_forms_and_uploading_files">此文</a></p>

<h2 id="Firefox私有方法">Firefox私有方法</h2>

<p>下面的例子使用了<code>POST</code>请求,用Firefox私有的非标准方法<code>sendAsBinary()</code>将二进制数据以异步模式传输了出去.</p>

<pre class="brush: js notranslate">var req = new XMLHttpRequest();
req.open("POST", url, true);
// 这里应该设置适当的MIME请求头
req.setRequestHeader("Content-Length", 741);
req.sendAsBinary(aBody);
</pre>

<p>第四行将Content-Length请求头设置为741,表示发送的数据长度为741个字节.你应该根据你要发送的数据的大小改变这个值.</p>

<p>第五行使用<code>sendAsBinary()</code>方法发送这个请求.</p>

<p>你也可以通过将一个{{ interface("nsIFileInputStream") }}对象实例传给<a class="internal" href="/zh-cn/DOM/XMLHttpRequest#send()" title="/zh-cn/XMLHttpRequest#send()"><code>send()</code></a>方法来发送二进制内容,这样的话,你不需要自己去设置<code>Content-Length请求头</code>的大小,程序会自动设置:</p>

<pre class="brush: js notranslate">// 新建一个文件流.
var stream = Components.classes["@mozilla.org/network/file-input-stream;1"]
                       .createInstance(Components.interfaces.nsIFileInputStream);
stream.init(file, 0x04 | 0x08, 0644, 0x04); // file是一个nsIFile对象实例

// 设置文件的MIME类型
var mimeType = "text\/plain";
try {
  var mimeService = Components.classes["@mozilla.org/mime;1"]
          .getService(Components.interfaces.nsIMIMEService);
  mimeType = mimeService.getTypeFromFile(file); // file是一个nsIFile对象实例
}
catch (oEvent) { /* 丢弃异常,使用默认的text/plain类型 */ }

// 发送
var req = Components.classes["@mozilla.org/xmlextras/xmlhttprequest;1"]
                    .createInstance(Components.interfaces.nsIXMLHttpRequest);
req.open('PUT', url, false); /* 同步模式! */
req.setRequestHeader('Content-Type', mimeType);
req.send(stream);
</pre>

<p>{{APIRef("XMLHttpRequest")}}</p>