ajax传递二进制数据,AJAX传输二进制数据

FormData对象

将整个表单元素映射成一个对象,可实现自动拼接表单对象数据成请求参数的格式

可以上传二进制数据

利用FormData上传文本数据的表单:

前端网页核心代码:

用户名 =

密码 =

"use strict"

var myform = document.getElementById('myform');

var formdata; // 如果现在执行`formdata = new FormData(myform)`会导致formdata中的表单数据是空

function doit(){

formdata = new FormData(myform);

// FormDate API:https://developer.mozilla.org/zh-CN/docs/Web/API/FormData

var xhr = new XMLHttpRequest();

if (formdata.get('username') == 'nat'){ // IE11支持FormData构造器但是不支持get、set等一些方法

formdata.set('usernameOrigin', 'nat');

formdata.set('username', 'natasha'); // 同名的键会覆盖

formdata.delete('pwd');

formdata.append('username', 'natashe'); // 同名的键会保留

}

for (let x of formdata){

console.log(x); // 如果'username'传入的是'nat'那么输出如下:

// Array [ "username", "natasha" ]

// Array [ "usernameOrigin", "nat" ]

// Array [ "username", "natashe" ]

// 如果服务器不进行特殊设置,那么username只能获取到最后一次的值,即'natashe'(设置略)

}

xhr.open('POST', '/postdata');

xhr.send(formdata); // 会自动将'Content-Type'设置成'multipart/form-data; boundary=---------------------------20808984378436579741074229525'

// 注意,FormData数据在Node中不能通过中间件body-parser获取,尝试通过`req.body`获取始终返回空对象,而是通过`cnpm install --save formidable`这个模块获取,注意,它不是中间件

xhr.onload = function(){

if (xhr.status == 200){

console.log(xhr.responseText);

}else{

console.log('Something error happened: ', xhr);

}

}

}

后端Node核心代码:

const formidable = require('formidable');

app.post('/postdata', (req,res)=>{

var form = new formidable.IncomingForm();

form.parse(req, (err, fields, files)=>{

// fields是普通的表单数据(文本)

// files是上传的文件数据

console.log(fields);

res.send({id:20, data:[22,11,14,24]});

});

});

利用FormData上传二进制数据的本地文件:

前端网页核心代码:

昵称 =

文件 =

"use strict"

var myform = document.getElementById('myform');

var formdata;

function doit(){

formdata = new FormData(myform);

var xhr = new XMLHttpRequest();

xhr.open('POST', '/postdata');

xhr.upload.onprogress = function(e){

// 这个事件必须在send之前监听有效,在send之后监听不会触发

console.log(`当前进度:${Math.floor(e.loaded / e.total * 100)}%`);

}

xhr.send(formdata);

xhr.onload = function(){

if (xhr.status == 200){

console.log(xhr.responseText);

}else{

console.log('Something error happened: ', xhr);

}

}

}

后端Node核心代码:

app.post('/postdata', (req,res)=>{

var form = new formidable.IncomingForm();

form.uploadDir = './webroot/uploads'; // 上传的文件保存在哪个目录

form.keepExtensions = true; // 保留上传时的后缀名

form.parse(req, (err, fields, files)=>{

// fields是普通的表单数据(文本)

// files是上传的文件数据

console.log(fields);

console.log(files.doc.path); // 'webroot\\uploads\\upload_4242811d6678445365bbc7c55c0a968f.dat'

res.send({id:20, data:[22,11,14,24]});

});

});

XHR上传和下载二进制数据(TypedArray和Blob)

TypedArray

前端传给后端

// 前端

var data = new ArrayBuffer(64);

var dataview = new Uint8Array(data);

for (let i=0; i

dataview[i] = 97 + (i % 26); // 将64字节的二进制数据初始化成[a-z]的小写字母

}

dataview[data.byteLength-1] = 0;

function doit(){

var xhr = new XMLHttpRequest();

xhr.open('POST', '/postdata');

// xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // 表示通用二进制流,可不写

xhr.send(data);

xhr.onload = function(){

if (xhr.status == 200){

console.log(xhr.responseText);

}else{

console.log('Something error happened: ', xhr);

}

}

}

// 通过抓包,send出去的报文就是ArrayBuffer的二进制数据

// Node原生http服务器收到的POST数据默认是Buffer类型

// 后端

app.post('/postdata', (req,res)=>{

var tmpchunk = [];

var data;

req.on('data', (chunk)=>{

tmpchunk.push(chunk);

});

req.on('end', ()=>{

data = Buffer.concat(tmpchunk);

console.log(data);

res.send('ok');

})

});

后端传给前端

// 前端

function doit(){

var xhr = new XMLHttpRequest();

xhr.open('GET', '/getdata');

xhr.responseType = 'arraybuffer';

xhr.send();

xhr.onload = function(){

if (xhr.status == 200){

console.log(xhr.response); // ArrayBuffer 字节长度:8

}else{

console.log('Something error happened: ', xhr);

}

}

}

// 后端

app.get('/getdata', (req,res)=>{

res.set('Content-Type','application/octet-stream');

var data = new ArrayBuffer(8);

var dataview = new Uint8Array(data);

dataview[1] = 11;

dataview[3] = 22;

dataview[5] = 33;

dataview[7] = 44;

data = Buffer.from(data); // 将ArrayBuffer转换成Buffer

res.send(data); // 如果直接返回ArrayBuffer,会被JSON化成'{}'(注意,实际没有单引号,这里只做分隔符),只能传入Buffer才能使send方法正确发送二进制数据,通过抓包得到的响应体的数据是:00 0b 00 16 00 21 00 2c

});

Blob

前端传给后端

var data = new Blob(['haha']);

function doit(){

var xhr = new XMLHttpRequest();

xhr.open('POST', '/postdata');

// xhr.setRequestHeader('Content-Type', 'application/octet-stream'); // 表示通用二进制流,可不写

xhr.send(data);

xhr.onload = function(){

if (xhr.status == 200){

console.log(xhr.responseText);

}else{

console.log('Something error happened: ', xhr);

}

}

}

// 原理同ArrayBuffer,send出去的报文就是Blob的二进制数据,报文的请求体:h a h a

后端传给前端

// 注意,Node不存在Blob,只需要传递Buffer即可,故此后端代码同【TypedArray的后端传给前端】

// 前端:将xhr.responseType = 'arraybuffer' -> 'blob',获取到的xhr.response返回`Blob{size: 8, type: "application/json"}`,其中的type会被自动设置成响应头中的'Content-Type'

旧时代的二进制传输

在xhr.responseType还没有'arraybuffer'、'blob'甚至'json'的时代,B/S传递二进制只能通过表单上传和文件下载,AJAX还没有传递二进制的API,但是可以hack出来,如下,

// 前端

function doit(){

var xhr = new XMLHttpRequest();

xhr.open('GET', '/getdata');

// xhr.overrideMimeType('Content-Type', 'text/plain; charset=x-user-defined'); // 告诉浏览器不要尝试去解析字符串,不加这行其实也行

xhr.send();

xhr.onload = function(){

if (xhr.status == 200){

// console.log(xhr.getAllResponseHeaders()); // 即便上面已经覆盖了,但是获取到的还是原始的响应头

// debugger

var data = xhr.response;

var len = data.length;

console.log(len); // 不能直接输出data,会乱码,尝试检测收到的数据的长度,输出4,正确

var received = new ArrayBuffer(len);

var receivedview = new Uint8Array(received);

for (let i=0; i

receivedview[i] = data.charCodeAt(i);

}

console.log(receivedview); // 输出Uint8Array(6)[70, 126, 127, 253, 253, 253]

// 得出结论:采用这种方式后端只能传递[0, 127]范围的字节

}else{

console.log('Something error happened: ', xhr);

}

}

}

// 后端

app.get('/getdata', (req,res)=>{

var data = Buffer.allocUnsafe(4);

data[0] = 70; data[1] = 126; data[2] = 127; data[3] = 128; data[4] = 129; data[5] = 255;

res.send(data);

});


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部