XMLHttpRequest发布多部分FormData,文件被添加两次

时间:2018-02-12 14:05:29

标签: javascript ajax file-upload

我正在使用XMLHttpRequest和FormData创建上传机制。但是,在创建请求时,文件会以某种方式添加两次,我在这里缺少什么?

我有一个班级Uploader负责提交多部分表单和一个负责实际上传的静态对象cc

当单个输入字段调度Uploader事件时,将从JS调用change - 类的上传方法。

Uploader类如下所示:

class Uploader {
    constructor(form){
        this._form = form;
        this._files = [];
    }

    _buildFileIndex(){
        const fileInputsEl = this._form.querySelectorAll('input[type="file"]');
        const fileInputs = Array.from(fileInputsEl).map(input => {
            return {
                'name': input.getAttribute('name') || 'undefined',
                'files': input.files
            }
        });

        this._fileInputs = fileInputs;
        return fileInputs;
    }

    _buildFormData(){
        this._formData = new FormData(this._form);
        for(let input of this._fileInputs){
            for(let file of input.files){
                this._formData.append(input.name, file, file.name);
            }
        }

        return this._formData;
    }

    upload(callback){
        this._buildFileIndex();
        this._buildFormData();

        cc.POST('/api/upload', this._formData, res => {
            if(typeof callback === 'function') callback(res);
        });
    }
}

cc对象:

const cc = {
    'serverADDR': function(){return window.location.protocol + '//' + window.location.host},
    'POST': function(endpoint, data, callback, contentType){
        const xhttp = new XMLHttpRequest();
        xhttp.open('POST', cc.serverADDR() + endpoint, true);

        if(contentType) xhttp.setRequestHeader('Content-Type', contentType);

        xhttp.onreadystatechange = function() {
            if (this.readyState == 4 && this.status == 200) {
                if(typeof callback === 'function') callback(this);
            }
        };

        xhttp.send(data);
    }
}

这是根据Google Chrome发送的数据,只在一个输入中选择一个文件:

------WebKitFormBoundaryEDgRU4CNKJQjnIA8
Content-Disposition: form-data; name="media"; filename="Skärmavbild 2017-10-29 kl. 12.16.50.png"
Content-Type: image/png


------WebKitFormBoundaryEDgRU4CNKJQjnIA8
Content-Disposition: form-data; name="media"; filename="Skärmavbild 2017-10-29 kl. 12.16.50.png"
Content-Type: image/png


------WebKitFormBoundaryEDgRU4CNKJQjnIA8--

表单的提交是在特定于页面的对象home中进行的:

const home = {
    'el': {
        'inputs': {
            'form': document.querySelector('form'),
            'input': document.querySelector('input')
        }
    },
    'init': function(){
        home.setupForm();
    },
    'setupForm': function(){
        home.el.inputs.input.addEventListener('change', home.upload);
    },
    'upload': function(){
        const uploader = new Uploader(home.el.inputs.form);
        uploader.upload(res => {
            console.log(res);
        });
    }
}

home.init();

...表单本身就像:

<form method="POST" action="#">
    <input type="file" name="media">
</form>

1 个答案:

答案 0 :(得分:0)

创建FormData实例会自动附加提供的表单的字段。因此,在发送请求之前,所有文件都被添加了两次。