How to manually create multipart/form-data

前端 未结 2 610
天涯浪人
天涯浪人 2020-12-09 23:11

We can use .formData() of Body mixin to return a FormData representation of data at Chromium (Chrome) 60+ and Firefox 39+

Relevant specifications:

相关标签:
2条回答
  • 2020-12-09 23:47

    You can write you own FormData polyfill, or just google it "FormData polyfill"))) And also you can use normal FormData at browsers Chrome, FireFox, Opera, Safari, IE(10+), Edge. FormData polyfill is only useful for old IE, and for workers, but for workers you better should use this - https://gist.github.com/Rob--W/8b5adedd84c0d36aba64

    wikipedia

    standart formdata not of body

    What you need to do? You want send formdata or recieve it at js?

    You can try to use my polyfill, but I have not tested it.

    sample:

    var data = new RawFormData();
    data.append("key","value")
    data.append("key", new Blob("test"), "my file.txt");
    data.getOutputDeferred().then(function(formData){
        var xml = new XMLHttpRequest();
        xml.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + data.getBoundry());
        xml.setRequestHeader("Content-Length", formData.length);
        xml.open(method, url);
        xml.send(formData);
    });
    

    code:

    /**
    * @constructor
    */
    RawFormData = function () {
        this._promises = [];
        this._boundry = this.makeBoundary();
    };
    
    /**
    * @return {string}
    */
    RawFormData.prototype.getBoundary = function () {
        return this._boundry;
    }
    
    /**
    * @return {string}
    */
    RawFormData.prototype.makeBoundary = function () {
        return 'MyBoundary' + window.btoa(Math.random().toString()).substr(0, 12);
    };
    
    /**
    * @param {string} name
    * @param {string|number|File|Blob|boolean|null|undefined} val
    * @param {string=} filename
    */
    RawFormData.prototype.append = function (name, val, filename) {
        var prom = null;
    
        if(val instanceof File || val instanceof Blob){
            prom = this.readAsBinaryString(val).then(function(base64){
                var contentType = val.type || 'application/octet-stream';
                var result = '--' + this._boundry + '\r\n' +
                    'Content-Disposition: form-data; ' +
                    'name="' + name + '"; filename="' + this.encode_utf8(filename || "blob") + '"\r\n' +
                    'Content-Type: ' + contentType + '\r\n\r\n' +
                    base64 + '\r\n';
                return result;
            }.bind(this))
        }else{
            prom = new Promise(function(resolve){
                return '--' + this._boundry + '\r\n' +
                    'Content-Disposition: form-data; ' +
                    'name="' + this.encode_utf8(name) + '"\r\n\r\n' +
                    this.encode_utf8(val) + '\r\n'
            }.bind(this));
        }
    
        this._promises.push(prom);
    
        return prom;
    };
    /**
    * @return {File|Blob} blob
    * @return {Promise<string>}
    */
    RawFormData.prototype.readAsBinaryString = function (blob) {
            var reader = new FileReader();
            return new Promise(function(resolve,reject){
                var binStringCallback = function (e) {
                    resolve(e.target.result);
                };
    
                var arrBufferCallback = function (e) {
                    var binary = "";
                    var bytes = new Uint8Array(e.target.result);
                    var length = bytes.byteLength;
                    for (var i = 0; i < length; i++) {
                        binary += String.fromCharCode(bytes[i]);
                    }
                    resolve(binary);
                };
    
                reader.onerror = reader.onabort = function () {
                    resolve(null);
                };
    
                if (typeof reader.readAsBinaryString != "undefined") {
                    reader.onload = binStringCallback;
                    reader.readAsBinaryString(blob);
                } else {
                    reader.onload = arrBufferCallback;
                    reader.readAsArrayBuffer(blob);
                }
            });
    };
    
    RawFormData.prototype.encode_utf8 = function( s ){
       return unescape( encodeURIComponent( s ) );
    }
    
    RawFormData.prototype.getOutputDeferred = function () {
        return Promise.all(this._promises).then(function (rows) {
            var output = '--' + this._boundry + '\r\n';
            rows.forEach(function(row) {
                output += row;
            });
            output += '--' + this._boundry + '\r\n';
            return output;
        }.bind(this));
    };
    
    0 讨论(0)
  • 2020-12-10 00:01

    You can create multipart/form-data manually with XMLHttpRequest like this example.

    function multiPost(method, url, formHash){
        var boundary = "nVenJ7H4puv"
        var body = ""
        for(var key in formHash){
            body += "--" + boundary
                 + "\r\nContent-Disposition: form-data; name=" + formHash[key].name
                 + "\r\nContent-type: " + formHash[key].type
                 + "\r\n\r\n" + formHash[key].value + "\r\n"
        }
        body += "--" + boundary + "--\r\n"
    
        var xml = new XMLHttpRequest();
        xml.open(method, url)
        xml.setRequestHeader("Content-Type", "multipart/form-data; boundary=" + boundary)
        xml.setRequestHeader("Content-Length", body.length)
        xml.send(body)
    }
    
    0 讨论(0)
提交回复
热议问题