模拟FormData创建表单请求

Posted ksyy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟FormData创建表单请求相关的知识,希望对你有一定的参考价值。





class AppendStatus{
    successed = false;
    constructor(){

    }
    success(listenEvent){
        this.successed = true;
        if(listenEvent){
            listenEvent.run();
        }
    }
    getStatus(){
        return !!this.successed
    }
}

class ListenEvent{
    callback;
    appendStatusCache = [];
    isRuned = false;
    constructor(callback = ()=>{},appendStatusCache = []){
        this.callback = callback;
        this.appendStatusCache = appendStatusCache;
    }
    run(){
        var ct = 0;
        for(var i =0,l=this.appendStatusCache.length;i<l;i++){
            if(this.appendStatusCache[i].getStatus()){
                ct +=1;
            };
        };
        if(ct >= this.appendStatusCache.length && !this.isRuned){
          console.log("run success",ct);
            this.callback();
            this.isRuned = true;
        }
    }
}
class OurFormData {
    // data;
    rs;
    callback;
    appendStatusCache = [];
    listenEvent;
    constructor(rs) {
        // this.data = data;
        this.rs = rs;
        // this.callback = callback;
    }

    append(k,v){
        var appendStatus = new AppendStatus();
        this.appendStatusCache.push(appendStatus);
        
        let data_string = ‘ ‘
        this.segments = []
        // this.rs = rs
        this.status = 0
        let resolve = ()=>{
            appendStatus.success(this.listenEvent);
        }
        // let result = new Promise(res => resolve = res)
        
        // let k, v
        let getTag = v => ({}).toString.call(v)
        // for ([k, v] of Object.entries(data)) {
        // }
        let tag = getTag(v)
        console.log("append2",k,v,tag);
        if (tag === ‘[object File]‘) {
          // 单文件
          let render = new FileReader()
          render.readAsBinaryString(v);
          // render.index = this.segments.length
          var index;

          render.onload = ({
            target: {
              result
            }
          }) => {
            console.log("onload",k,v,tag);
            this.segments[index] += `${result || ‘‘} `;
            // this.status--

            // 所有异步全部完成
            if (this.status === 0) {
              resolve()
            }
          }

          
          index = this.segments.push(
            `------WebKitFormBoundary${this.rs||‘‘} Content-Disposition: form-data; name="${k || ‘‘}"; filename="${v.name || ‘‘}" Content-Type: "${v.type || ‘‘}" `
          )
        //   this.status++
        } else if (tag === ‘[obejct Array]‘ && v.length > 0 && getTag(v[0]) === ‘[object File]‘) {
          // 多文件
          let file, render
          for (file of v) {
            render = new FileReader()
            render.readAsBinaryString(file);
            var index;

            render.onload = ({
              target: {
                result
              }
            }) => {
              this.segments[index] += `${result||‘‘} `
            //   this.status--

              // 所有异步全部完成
              if (this.status === 0) {
                resolve()
              }
            }

            index = this.segments.push(
              `------WebKitFormBoundary${this.rs||‘‘} Content-Disposition: form-data; name="${k || ‘‘}"; filename="${v.name || ‘‘}" Content-Type: "${v.type||‘‘}" `
            )
            // this.status++
          }
        } else if(tag === ‘[object ArrayBuffer]‘){
            console.log("[object ArrayBuffer]",v);
        } else if (tag === ‘[object Array]‘) {
          // 处理数组, age: [12, 14]
          let $_
          for ($_ of v) {
            this.segments.push(
              `------WebKitFormBoundary${this.rs||‘‘} Content-Disposition: form-data; name="${k||‘‘}" ${$_||‘‘} `
            )
          }
          resolve()
        } else {
          // string and number
          this.segments.push(
            `------WebKitFormBoundary${this.rs||‘‘} Content-Disposition: form-data; name="${k||‘‘}" ${v||‘‘} `
          )
          resolve()
        }
        // if (this.status === 0) {
        //   resolve(this.handleResData(this.segments))
        // }
        // return result
    }

    handleResData(segments = this.segments) {
        segments.unshift(` `)
        segments.push(`------WebKitFormBoundary${this.rs||‘‘}--`)
        let data = segments.join(‘‘)

        let bytes = data.length
        console.log("handleResData",segments,bytes);
        // let view = new Uint8Array(bytes)
        // for (let i = 0; i < bytes; i++) {
        //   view[i] = data.charCodeAt(i) & 0xff
        // }
        let buffer = new ArrayBuffer(bytes)
        let view = new DataView(buffer, 0)
        let i
        for (i = 0; i < bytes; i++) {
        // & 0xff https://www.cnblogs.com/think-in-java/p/5527389.html
        // view.setUint8(i, data.charCodeAt(i) & 0xff)
        view.setUint8(i, data.codePointAt(i) & 0xff)
        }
        return view
    }

    ready(callback){
        this.listenEvent = new ListenEvent(callback,this.appendStatusCache);
        this.listenEvent.run();
    }
}


    return new Promise((res,rej) =>{
        
        //   let data = {
        //     name: ‘ajanuw‘,
        //     age: [1,2]
        //   }
        // Object.assign(data, {
        //   file
        // })

        let rs = Date.now().toString(16)
        let sendData = new OurFormData(rs)
        try{
          
            var reader = new FileReader();
            reader.readAsArrayBuffer(file);
            reader.onload = function (e) {
                console.info(reader.result); //ArrayBuffer {}
                //经常会遇到的异常 Uncaught RangeError: byte length of Int16Array should be a multiple of 2
                //var buf = new int16array(reader.result);
                //console.info(buf);

                //将 ArrayBufferView  转换成Blob
                var buf = new Uint8Array(reader.result);
                
                sendData.append("file",reader.result);
                sendData.ready(()=>{
                    var formData = sendData.handleResData();



                    console.log("new beforeUpload222",sendData,formData)
                    fetch(this.$uploadUrl, {
                        method: ‘POST‘, // or ‘PUT‘
                        body: formData,
                        headers: new Headers({
                          // ‘Content-Type‘: ‘multipart/form-data‘
                          // ‘Content-Type‘: ‘application/json‘
                          "Content-Type":`multipart/form-data; boundary=----WebKitFormBoundary${rs||‘‘}`
                        })
                      }).then(res => res.json())
                      .catch(error => console.error(‘Error:‘, error))
                      .then(response => console.log(‘Success:‘, response));
                })
            }
            
        }catch(e){
          console.log("Error:",e)
        }
        rej();
      })

以上是关于模拟FormData创建表单请求的主要内容,如果未能解决你的问题,请参考以下文章

js 上传文件模拟Form 表单

H5:使用formData对象模拟表单

FormData对象的使用

FormData 和 Content-Type: multipart/form-data

FormData

FormData