原生JS封装xhr和ajax请求二进制blob数据
请求二进制
jquery中的ajax是不支持请求二进制的,前端通过jQuery ajax接受后端的文件流,前端下载文件后内容乱码。
原因分析:jQuery ajax response 类型只能是:xml, html,script,json,jsonp,text。 无法接受blob类型的response。 当后端返回给前端一个文件流的时候,前端ajax会将文件流转化成string 类型。 无法正确读取改文件流,导致文本内容乱码。从而导致blob转义成base64也会失败。
所以获取二进制blob的最好方法就是,使用原生js封装一个方法。
首先是将二进制转换成base64
// 二进制流转换为base64 格式。
function getBase64(data) {
return new Promise((resolve, reject) => {
const blob = new Blob([data], { type: "image/png" }); // 必须指定type类型
const reader = new FileReader();
reader.readAsDataURL(blob);
reader.onload = () => resolve(reader.result);
reader.onerror = (error) => reject(error);
});
}
封装一个post请求二进制数据
/**
* url:post请求的地址
* args:传入的参数,这里单指传入的formdata数据
* success:成功后的回调函数
* */
function getBinary(url, args, success) {
// 1. 创建 xhr 对象
const xhr = new XMLHttpRequest();
// 2. 调用 open 函数
xhr.open('POST', url, true);
// 3. 设置 Content-Type 属性(固定写法)
// Content-Type: multipart/form-data;
// xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
//4. 定义responseType='blob', 是读取文件成功的关键,这样设置可以解决下载文件乱码的问题
xhr.responseType = "blob";
xhr.onreadystatechange = function () {
console.log(xhr.readyState, xhr.status)
if (xhr.readyState === 4 && xhr.status === 200) {
// var responseText = xhr.responseText; 不能使用这个获取结果
//返回二进制数据流
// console.log(responseText);
console.log(xhr)
console.log(xhr.response)
// 执行成功后的回调
success(xhr.response)
}
}
// 4. 调用 send 函数发送携带的数据
xhr.send(args);
}
Uncaught DOMException: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').
注意,这个报错的意思就是,当 xhr.responseType="text";的时候,才可以使用 xhr.responseText 去获取结果,而这个xhr.responseType="blob";设置成blob,所以无法通过xhr.responseText获取返回值,必须通过xhr.response。
点击选择文件按钮,发送请求,并转换为base64插入到html中
// 找了个python的扣图接口rembg 部署在服务器上
const posturl = 'http://172.20.65.171:5000';
<input type="file" name="file" id="upload-img"/>
<div class="box">
<img alt="展示处理后的图片" id="image-alpha">
</div>
$('#upload-img').on('change', function(e) {
var file = e.target.files[0]
// console.log(file)
var fd = new FormData()
fd.append('file', file)
getBinary(posturl, fd, function(response) {
getBase64(response).then((result) => {
console.log(result)
result = result.replace(/[\r\n]/g, '')
$('#image-alpha').attr('src', result);
});
});
原生JS封装基本的ajax请求
封装简单的get
// 1. 创建 XHR 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open 函数
xhr.open('GET', 'http://www.liulongbin.top:3006/api/getbooks')
// 3. 调用 send 函数
xhr.send()
// 4. 监听 onreadystatechange 事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
// 获取服务器响应的数据
console.log(xhr.responseText)
}
}
封装简单的post
// 1. 创建 xhr 对象
var xhr = new XMLHttpRequest()
// 2. 调用 open 函数
xhr.open('POST', 'http://www.liulongbin.top:3006/api/addbook')
// 3. 设置 Content-Type 属性(固定写法)
xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded')
// 4. 调用 send 函数
xhr.send('bookname=水浒传&author=施耐庵&publisher=上海图书出版社')
// 5. 监听事件
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText)
}
}
记住,如果请求二进制,xhr.responseType ="blob"; 一定要设置为blob
jq中用ajax上传图片
比如将这个表单,改成异步上传
<form
action="http://http://0.0.0.0:5000"
method="post"
enctype="multipart/form-data"
>
<input type="file" name="file" />
<input type="submit" value="upload" />
</form>
使用jq改造一下:
<input type="file" id="input-file">
$("#input-file").change(function(e) {
var file = e.target.files[0]
console.log(file)
var fd = new FormData()
fd.append('file', file)
ajax(fd)
})
function ajax(data) {
$.ajax({
url: "xxx",
dataType: "json",
// 默认请求是true异步,false代表同步
async: false,
// 传递formdata必须要带这两个参数
processData: false,
contentType: false,
data: data,
type: "POST",
success(res) {
console.log(res)
if (res.code == 0) {
..
} else {
alert(res.code)
}
},
error(err) {
console.log(err)
}
})
}