使用FormData接口实现AJAX上传文件
使用AJAX和JSON是现在和服务器进行通信的标准形式,但是直接这样对file类型的input的内容进行上传是无法成功的。因为对文件进行序列化后得到的是一个空对象。
1
<input type="file" id="file-uploader" />
1
2
3
4
5
6
7
8
const fileUploader = document.querySelector('#file-uploader');
const fileHandleUrl = '/example/file-upload';
fileUploader.addEventListener('change', () => {
const file = this.files[0];
console.log(JSON.stringify(file)); // => "{}"
});
这显然不是我们想要的。要如何才能上传成功呢?很简单,使用FormData接口就好了。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
const fileUploader = document.querySelector('#file-uploader');
const fileHandleUrl = '/example/file-upload';
fileUploader.addEventListener('change', function() {
const file = this.files[0];
const form = new FormData();
form.append('Content-Type', 'multipart/form-data');
form.append('file', file);
const xhr = new XMLHttpRequest();
xhr.onload = () => {
// 文件上传成功逻辑
};
xhr.onerror = () => {
// 文件上传出错的逻辑
};
xhr.open('POST', fileHandleUrl);
xhr.send(form);
this.value = '';
});
示例中直接使用的XMLHttpRequest实现AJAX,实际生产中,使用superagent或者其他模块更好。
服务器端处理也很简单,这里以express为例。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
'use strict';
const path = require('path');
const express = require('express');
const formidable = require('formidable');
const app = express();
app.use(express.static(path.join(__dirname, 'public')));
app.post('/example/file-upload', (req, res, next) => {
const form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
// 文件在files对象中
// 处理上传的文件的逻辑
res.send('success');
});
});
app.listen(3000, () => {
console.log('http://localhost:3000');
});
因为使用类型为multipart/form-data的表单上传,所有需要使用第三方模块处理类型为multipart/form-data的数据,这里使用的是formidable,还有其他选择,使用自己认为最适合的就好。