【发布时间】:2018-02-12 14:05:29
【问题描述】:
我正在使用 XMLHttpRequest 和 FormData 制作上传机制。但是,在创建请求时,文件以某种方式被添加了两次,我在这里缺少什么?
我有一个类 Uploader 负责提交多部分表单,一个静态对象 cc 负责实际上传。
Uploader-class 的上传方法是在单个输入字段调度 change 事件时从 JS 调用的。
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);
}
}
这是根据谷歌浏览器发送的数据,当一个输入只选择一个文件时:
------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>
【问题讨论】:
-
嗯,很奇怪。它一直在发生,起初我认为这是特定于浏览器的问题,但它发生在 Chrome 和 Safari 中。
-
@Andreas 在我看来,即使在您的 plunker 中也确实会发生这种情况。查看发送的请求时,即使在那里也添加了两个文件。
-
对不起,我以为你在谈论两个请求... :|
-
new FormData(this._form);这将创建一个新的FormData对象,其中包含传递表单的所有输入元素。之后,您手动添加所有输入字段 -> 1 + 1 = 2 -
啊,所以它在初始化FormData实例时已经从表单中添加了字段?
标签: javascript ajax file-upload