原生JS封装xhr和ajax请求二进制blob数据

18675次阅读 1410人点赞 作者: WuBin 发布时间: 2023-02-28 14:47:58
扫码到手机查看

请求二进制

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)
        }
    })
}

相关资料

点赞 支持一下 觉得不错?客官您就稍微鼓励一下吧!
关键词:blob,xhr
推荐阅读
  • uniapp实现被浏览器唤起的功能

    当用户打开h5链接时候,点击打开app若用户在已经安装过app的情况下直接打开app,若未安装过跳到应用市场下载安装这个功能在实现上主要分为两种场景,从普通浏览器唤醒以及从微信唤醒。

    9119次阅读 589人点赞 发布时间: 2022-12-14 16:34:53 立即查看
  • Vue

    盘点Vue2和Vue3的10种组件通信方式

    Vue中组件通信方式有很多,其中Vue2和Vue3实现起来也会有很多差异;本文将通过选项式API组合式API以及setup三种不同实现方式全面介绍Vue2和Vue3的组件通信方式。

    3884次阅读 289人点赞 发布时间: 2022-08-19 09:40:16 立即查看
  • JS

    几个高级前端常用的API

    推荐4个前端开发中常用的高端API,分别是MutationObserver、IntersectionObserver、getComputedstyle、getBoundingClientRect、requ...

    14139次阅读 919人点赞 发布时间: 2021-11-11 09:39:54 立即查看
  • PHP

    【正则】一些常用的正则表达式总结

    在日常开发中,正则表达式是非常有用的,正则表达式在每个语言中都是可以使用的,他就跟JSON一样,是通用的。了解一些常用的正则表达式,能大大提高你的工作效率。

    12947次阅读 445人点赞 发布时间: 2021-10-09 15:58:58 立即查看
  • 【中文】免费可商用字体下载与考证

    65款免费、可商用、无任何限制中文字体打包下载,这些字体都是经过长期验证,经得住市场考验的,让您规避被无良厂商起诉的风险。

    11539次阅读 926人点赞 发布时间: 2021-07-05 15:28:45 立即查看
  • Vue

    Vue3开发一个v-loading的自定义指令

    在vue3中实现一个自定义的指令,有助于我们简化开发,简化复用,通过一个指令的调用即可实现一些可高度复用的交互。

    15646次阅读 1248人点赞 发布时间: 2021-07-02 15:58:35 立即查看
  • JS

    关于手机上滚动穿透问题的解决

    当页面出现浮层的时候,滑动浮层的内容,正常情况下预期应该是浮层下边的内容不会滚动;然而事实并非如此。在PC上使用css即可解决,但是在手机端,情况就变的比较复杂,就需要禁止触摸事件才可以。

    14843次阅读 1209人点赞 发布时间: 2021-05-31 09:25:50 立即查看
  • Vue

    Vue+html2canvas截图空白的问题

    在使用vue做信网单页专题时,有海报生成的功能,这里推荐2个插件:一个是html2canvas,构造好DOM然后转canvas进行截图;另外使用vue-canvas-poster(这个截止到2021年3月...

    29040次阅读 2281人点赞 发布时间: 2021-03-02 09:04:51 立即查看
  • Vue

    vue-router4过度动画无效解决方案

    在初次使用vue3+vue-router4时候,先后遇到了过度动画transition进入和退出分别无效的情况,搜遍百度没没找到合适解决方法,包括vue-route4有一些API都进行了变化,以前的一些操...

    25064次阅读 1931人点赞 发布时间: 2021-02-23 13:37:20 立即查看
交流 收藏 目录