javascript 如何手动创建多部分/表单数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/47080869/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 07:11:09  来源:igfitidea点击:

How to manually create multipart/form-data

javascriptmultipartform-data

回答by sapics

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

您可以multipart/form-data像这个示例一样使用 XMLHttpRequest 手动创建。

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

回答by Alex Nikulin

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

您可以编写自己的 FormData polyfill,或者只是在 google 上搜索“FormData polyfill”))) 并且您还可以在 Chrome、FireFox、Opera、Safari、IE(10+)、Edge 浏览器中使用普通 FormData。FormData polyfill 仅对旧 IE 和工人有用,但对于工人,您最好使用它 - https://gist.github.com/Rob--W/8b5addd84c0d36aba64

wikipedia

维基百科

standart formdata not of body

不属于正文的标准格式数据

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

你需要做什么?你想发送表单数据还是在 js 接收它?

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

你可以尝试使用我的 polyfill,但我还没有测试过。

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