Ajax获取图片的两种方式

2023-11-12

在Web项目中,我们可能遇到需要利用Ajax来获取图片的情况。因为客户端处理的是图片文件的二进制流,所以可利用Blob和File API来将图片转为URL,赋值给img的src属性来解决这个问题。本文总结Ajax获取图片的两种方式,即针对XMLHttpRequest Level 1和Level 2给出解决方案。(注意:若无说明,下文中所有xhr都代表XMLHttpRequest 对象)。PS:最近想到这种需求,于是阅读一些资料,整了一天,写了本篇文章。如有错误,请不吝指正。题外话:写博客贵在坚持呀!!!

  1. 首先给出html结构,因为重点讲Ajax,所以用一个很简单的例子来说明,页面只有一个button和一个img。

    <!--login.html的其他代码省略 -->
    <input type="button" id="btn">
    <!--获取的图片将在此显示-->
    <img id="preview">
  2. 因为Ajax要和后台交互,此处将使用Node.js完成后台的逻辑,逻辑同样很简单。只需对//upload做处理即可。Ajax将请求/upload的内容。当请求时,发送给客户端图片。代码如下:

    var http=require('http');
    var fs=require('fs');
    http.createServer((req,res)=>{
      console.log(`${req.method}:${req.url}`);
      if(req.url=='/'){
        res.writeHead(200,{'Content-Type':'text/html,charset=utf-8'});
        fs.createReadStream('login.html').pipe(res);
      }else if(req.url=='/upload'){
        if(req.method.toLowerCase()=='get'){
          fs.readFile('images/captcha.0953f.png',(err,file)=>{
            res.setHeader('Content-Length',file.length);
            console.log(file.length);
            res.writeHead(200,{'Content-Type':'image/png'});
            res.end(file);
          })
        }else{
          res.end('success');
          }
      }else{
          fs.readFile('.'+req.url,(err,file)=>{
          if(err){
            res.writeHead(404);
            res.end('Not found!');
          }
           fs.createReadStream('.'+req.url).pipe(res);
        })
      }
    }).listen(3000);
    
  3. Ajax请求图片的两种方式
    首先公共代码如下:

    window.onload=function(){
      var btn=document.getElementById('btn');
      btn.onclick=function(){
      sendRequest();
     }
    }
    • XMLHttpRequest level 1(兼容旧浏览器):利用overrideMimeType()方法,将xhr设置为xhr.overrideMimeType('text/plain;charset=x-user-defined');。其中text/plain表示把响应作为普通文本来处理;charset=x-user-defined表示使用用户自定义的字符集,以告诉浏览器不要去解析数据,直接返回未处理过的字节码。此步骤必须,不可忽略。之后就可以通过xhr.responseText取得响应文本,然后将其转为二进制数据,传递给Blob构造函数。而后,通过FileReaderreadAsDataURL()方法创建URL赋值给图片的src属性即可。具体代码如下:

      function sendRequest(){
          var xhr=new XMLHttpRequest();
          xhr.onload=function(){
            if(xhr.status>=200 && xhr.status<300){
              var binStr = this.responseText;
              //console.log(this.response==this.responseText);//true
              var arr = new Uint8Array(binStr.length);
              for(var i = 0, l = binStr.length; i < l; i++) {
      
                arr[i] = binStr.charCodeAt(i);
                //arr[i] = binStr.charCodeAt(i) & 0xff;
              }
              //console.log(binStr.charCodeAt(0).toString(16));
              //console.log(arr[0].toString(16));
              var blob=new Blob([arr.buffer],{type:'image/png'})
              loadImage_file(blob);
            }else{
              console.log('error');
            }
          }
          xhr.open('get','/upload',true);
          //兼容老浏览器。必须,以文本格式接受,字符集自定义
          xhr.overrideMimeType('text/plain;charset=x-user-defined');
          xhr.send(null);
        }
      function loadImage_file(blob){
          var fr=new FileReader();
          fr.readAsDataURL(blob);
          fr.onload=function(e){
            var preview=document.getElementById('preview');
            preview.src=e.target.result;
          }
        }

      该方法关键点是把响应文本转为二进制数据,利用字符串的charCodeAt(index)方法可以得到index位置的字符码,遍历整个字符串将其编码保存至Uint8Array中,而后传递给Blob来重构URL。关于arr[i] = binStr.charCodeAt(i) & 0xff;,表示在每个字符的两个字节之中,只保留后一个字节,将前一个字节扔掉。原因是浏览器解读字符的时候,会把字符自动解读成Unicode的0xF700-0xF7ff区段。但因为我用的是Uint8Array,它会自动截取低8位,所以做不做与运算也就无所谓了。

    • XMLHttpRequest level 2:设置xhr的responseType属性,指定为blob(或ArrayBuffer,如设置为ArrayBuffer,还要转Uint8Array,然后转成blob),例如,xhr.responseType='blob';。这样就可以通过xhr.response来获取该blob对象。注意不能用xhr.responseText来获取,因为该属性只在响应类型是“text”时有效,强行获取只会得到错误:Uncaught InvalidStateError: Failed to read the 'responseText' property from 'XMLHttpRequest': The value is only accessible if the object's 'responseType' is '' or 'text' (was 'blob').。该方法响应blob对象,所以无需对响应再做其他处理,只需传给FileReaderreadAsDataURL()就可以了。代码如下:

      function sendRequest(){
          var xhr=new XMLHttpRequest();
          xhr.onload=function(){
            if(xhr.status>=200 && xhr.status<300){
              var blob = this.response;
              //loadImage_file()方法与前面相同
              loadImage_file(blob);
            }else{
              console.log('error');
            }
          }
          xhr.open('get','/upload',true);
          xhr.responseType='blob';
          xhr.send(null);
        }

      从中可以看出,代码量大大减少,语法简洁而清晰。

总结:两种方式各有各的有点,方法一兼容性好,方法二清晰简洁。具体用那种,还看各位的想法了。
最后,给出几篇关于XMLHttpRequest的优秀文章:
1. 你真的会使用XMLHttpRequest吗?
2. XMLHttpRequest Level 2 使用指南

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Ajax获取图片的两种方式 的相关文章

随机推荐

  • C#教程(6)———— 比较运算符与逻辑运算符

    C 教程 6 比较运算符与逻辑运算符 前言 1 比较运算符 1 1 不同数据类型之间比较 1 2 使用比较运算符比较字符类型 1 3 其它数据类型比较 2 逻辑运算符 总结 前言 在之前的文章中 我们介绍了各种数学运算该怎么进行 而在数学中
  • java.lang.IllegalArgumentException: parameter must be a descendant of this view 的解决方案

    异常出现情况 mLayoutMap为布局view的集合 如当前view为view1可见visible 正常情况view2 view3 view4 为不可见gone 当点击tab2 让view2显示 时抛出上面的异常 分析以及解决方案 par
  • 原型链解释

    一 什么是原型链 原型链是javascript中用来实现类似类继承的一套机制 像链条一样把javascript中的对象连接起来 实现类似子联系父的现象 二 原型链的实现 总的来说 就是 对象的 proto 指向其构造器的prototype对
  • ahx文件转mav文件 工具分享及说明

    前言 今天用ndstool 拆了个nds的游戏 提取音频资源时发现格式为ahx 查了查网上都没有转换资料 格式工厂也不支持此格式 于是在github上找到了个好工具 分享一下 根据 文件格式查询信息库 数据统计 AHX 文件扩展名相关的格式
  • Docker8_2:Docker volume容器数据卷挂载:具名挂载和匿名挂载

    Docker8 2 Docker volume容器数据卷挂载 具名挂载和匿名挂载 docker volume 匿名挂载 不常用 具名挂载 常用 三种挂载方式 docker volume docker volume相关命令 docker 卷操
  • Qt Installer Framework的学习

    Qt Installer Framework的学习 Qt Installer Framework是Qt默认包的发布框架 它很方便 使用静态编译Qt制作而成 并且使用了压缩率很高的7z对组件进行压缩 之所以有这些好处 我才觉得值得花一点儿精力
  • 包装类之Integer案例学习

    引入 首先标题我写了学习Integer作为案例 是因为了解了一个包装类 其他便能深入浅出的学习到了 1 什么是包装类 以前定义变量 经常使用基本数据类型 对于基本数据类型来说 它就是一个数 加点属性 加点方法 加点构造器 将基本数据类型对应
  • 「Python 机器学习」Pandas 数据分析

    Pandas 是一个开源的 Python 库 专为数据处理和分析任务而设计 它提供了高性能 易用的数据结构和数据分析工具 使得在 Python 中进行数据科学变得简单高效 Pandas 基于 NumPy 因此可以与许多其他基于 NumPy
  • 蓝桥杯VIP试题 基础练习 龟兔赛跑预测C语言,C++

    试题 基础练习 龟兔赛跑预测 资源限制 时间限制 1 0s 内存限制 512 0MB 问题描述 话说这个世界上有各种各样的兔子和乌龟 但是研究发现 所有的兔子和乌龟都有一个共同的特点 喜欢赛跑 于是世界上各个角落都不断在发生着乌龟和兔子的比
  • 推荐系统综述:初识推荐系统

    目录 1 引言 2 发展历史 3 研究现状 4 推荐方式和效果评估 4 1 评分预测 4 2 TopN推荐 5 推荐算法 5 1 基于用户行为推荐 5 1 1 基于用户的协同过滤 User Based CF 5 1 2 基于物品的协同过滤
  • c++11新特性-可变参数模板

    在c 11中声明可变函数模板需要typename或者class后面跟上 省略号有两个作用 1 声明一个参数包 这个参数包可以有0到任意个参数 2 在模板定义的右边 可以将参数包展开成一个一个独立的参数 可变函数模板的定义 template
  • JAVA安装详细教程

    JAVA安装详细教程 如果下面的博客没有能解决你的问题或者你还有其他关于计算机方面的问题需要咨询可以加博主QQ 1732501467 JAVA安装总共分为三部分 一 下载JAVA安装包并安装JAVA 二 电脑环境设置 三 验证Java是否安
  • spring核心框架体系结构(jar包依赖)

    很多人都在用spring开发java项目 但是配置maven依赖的时候并不能明确要配置哪些spring的jar 经常是胡乱添加一堆 编译或运行报错就继续配置jar依赖 导致spring依赖混乱 甚至下一次创建相同类型的工程时也不知道要配置哪
  • stm32c8t6-PWM控制SG90舵机及用串口下载程序

    舵机是用PWM波控制的 学完PWM就可以简单的控制舵机啦 我用的是stm32c8t6单片机 高级定时器TIM1 CH1 使用通用定时器也行 大同小异 结果都一样 定时器部分的知识 代码网上都有 我这里不再赘述 开始之前我们先了解一下舵机的特
  • 树莓派3B安装64位操作系统

    树莓派3B 安装Ubuntu MATE 树莓派3b 安装ubuntu 雨田大大的博客 CSDN博客https blog csdn net lsjackson13 article details 92423694 utm medium dis
  • python3.8 Crypto.Cipher报错快速解决办法

    python3 8 Crypto Cipher报错快速解决办法 使用大佬编译好的whl安装包 把python3安装目录Lib和Lib site packges下的crypto改成Crypto 再安装crypto pip3 install c
  • OpenMV与STM32之间的通信

    OpenMV与STM32之间使用串口进行通信 OpenMV 详细解释可以看代码里面的注释 注意 转换成字节型传输时 负数会以补码形式传输 比如 1在单片机接受时变成255 import sensor image time math 调用声明
  • Apache Commons Daemon简介说明

    转自 Apache Commons Daemon简介说明 下文笔者讲述Apache Commons Daemon的功能简介说明 如下所示 Apache Commons Daemon的功能 用于将一个普通的java应用程序编程系统的后台服务
  • Qt信号和槽函数连接不成功原因

    Qt信号和槽连接失败原因主要有以下几点 1 槽函数并没有声明在类的public slots 或private slots或protected slots 里 因此 所想要成为槽函数的那个函数只是普普通通成员函数 2 信号和槽之间存在参数传递
  • Ajax获取图片的两种方式

    在Web项目中 我们可能遇到需要利用Ajax来获取图片的情况 因为客户端处理的是图片文件的二进制流 所以可利用Blob和File API来将图片转为URL 赋值给img的src属性来解决这个问题 本文总结Ajax获取图片的两种方式 即针对X