从简单封装ajax --- ajax上传图片

717 阅读2分钟

封装ajax

ajax都不陌生,其核心是XMlHttpRequest。

用到的知识点

在使用ajax的时候,首先得new出一个XMLHttpRequest的实例对象, 在更早的ie6中我们使用window.ActiveXObject。

因此第一段代码这样写:


    var Ajax ;
    if (window.XMLHttpRequest) {
      Ajax = new XMLHttpRequest();
    } else if (window.ActiveXObject) {
      Ajax = new ActiveXObject("Microsoft.XMLHTTP");
    }
    

这样我们得到了一个,Ajax的实例。 为了方便使用,需要对这个实例对象的使用过程进行封装,方便之后的使用。

那么首先我们得知道他是怎么工作的: 这里推荐阅读MDN文档:AJAX;

大概过程是:

声明实例 -> 通过open初始化一个请求 -> setRequestHeader设置请求头 -> send发送请求->在onreadystatechange中监听状态发生变, readyState===4(方法调用完成), status === 200(请求状态成功)时,获取到数据(这里获取到的数据一般存在responseText中)。

值得注意的是:

1、setRequestHeader设置请求头 必须在open之后,send之前。

2、返回数据一般存在responseText中,如果请求头中,content-type为 'application/json' 那么需要转JSON。

需要记录的是:

  • Ajax.readyState
    • 代表请求状态的状态码
  • Ajax.status
    • 代表请求的响应状态
  • Ajax.onreadystatechange
    • 接收一个方法(当ajax的请求状态发生改变的时候都会触发)。 在这个函数中可以通过 this.redyState 获取状态。
  • Ajax.open
    • 初始化一个请求
    • 参数:open(type,url+api,isAsync)
  • Ajax.send
    • 发送请求
    • 参数 send(data || JSON.parse(data))

简单的封装过程



function ajax (sendObj){

  let Ajax;

  const baseUrl = 'http://127.0.0.1:9090' ;

  if (window.XMLHttpRequest) {
    Ajax = new XMLHttpRequest();
  } else if (window.ActiveXObject) {
    Ajax = new ActiveXObject("Microsoft.XMLHTTP");
  }

  const {type,api,data,headers,dataType,success,fail,complete} = sendObj

  Ajax.onreadystatechange = function (){

    if(this.readyState === 4){
      complete && complete();
    }

    if(this.readyState === 4 && this.status === 200){
      try {
        success && success(JSON.parse(Ajax.responseText));
      }catch (err){
        success && success(Ajax.responseText);
      }
    }else{
      fail && fail();
    }

  };

  Ajax.open(type,baseUrl+api,true);

  let sendData = data

  if(dataType !== 'formData'){
    Ajax.setRequestHeader('Content-Type', 'application/json');
    sendData = JSON.stringify(data)
  }

  headers && setHeader(headers)

  Ajax.setRequestHeader('token', 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImlhdCI6MTYzNjM1Nzg1NCwiZXhwIjoxODA5MTU3ODU0fQ.Kw0DZcOhFqerNtP8Z9ohj_1Py-2MHtQwC6P6odVDgmw');

  Ajax.send(sendData);

  function setHeader(headers){
    for (const headersKey in headers) {
      if(headers.hasOwnProperty(headersKey)){
        Ajax.setRequestHeader(headersKey, headers[headersKey]);
      }
    }
  }
}

使用/以及过程

  ajax({
    type: "post",
    api: "/api/public/upload",
    data: formData,
    // 用来区分文件上传与否了,其他情况我都写死了为json格式
    dataType: "formData",
    // 可以使用headers对其进行重写
    headers:{'token':'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImlhdCI6MTYzNjM1Nzg1NCwiZXhwIjoxODA5MTU3ODU0fQ.Kw0DZcOhFqerNtP8Z9ohj_1Py-2MHtQwC6P6odVDgmw'},
    success: function (res) {
      let img = document.createElement('img')
      img.setAttribute('src',res.data.url)
      document.body.append(img)
    }
  });

文件上传前端

文件上传

不管是单文件上传,还是多文件上传。 前端就是控制 input框上的multiple属性就好。

  <input type="file" multiple id="file"/>

上传的时候时候需要指定上传为表单类型。可以通过 FromData对象添加。 部分浏览器步支持这个属性,可以通过from表单提交,先看FromData方式的。


  let file = document.getElementById('file');
  
  let formData = new FormData();
  
  for (let i = 0; i < file.files.length; i++) {
    formData.append("file", file.files[i]);
  }

  ajax({
    type: "post",
    api: "/api/public/upload",
    data: formData,
    headers:{'token':'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1aWQiOjEsImlhdCI6MTYzNjM1Nzg1NCwiZXhwIjoxODA5MTU3ODU0fQ.Kw0DZcOhFqerNtP8Z9ohj_1Py-2MHtQwC6P6odVDgmw'},
    dataType: "formData",
    success: function (res) {
      let img = document.createElement('img')
      img.setAttribute('src',res.data.url)
      document.body.append(img)
    }
  });
  

文件上传node koa2

node上传我们使用插件 koa-multer

定义存储位置。


const multer = require('koa-multer');

const storage = multer.diskStorage({
  destination: async function (req, file, cb) {
    cb(null, 'tmp/');
  },
  filename: function (req, file, cb) {
    const fileFormat = (file.originalname).split(".");
    cb(null, Date.now() + "." + fileFormat[fileFormat.length - 1]);
  }
});

const upload = multer({storage});

在node路由使用

  router.post('/upload', upload.fields([
    {
      name: 'file',
      maxCount: 1
    },
    {
      name: 'imgs',
      maxCount: 4
    }
  ]), async (ctx) => {
    console.log(ctx.req.files)
  });

在这个路由中,我么可以通过ctx.req.files拿到一个对象。

upload.png

这个对象中是可以拿到,上面定义的imgs 和 file两个对象的 都是数组。

至此 简单的ajax封装到简单的文件上传,就已经完成。