前后端(Vue + Node)实现上传文件并保存到服务器。input + axios + body-parser + fs 模块 读取写入数据。
前端
部分为 Vue 代码
使用 input(file)标签
<input name="file" type="file" multiple
ref="file"
@change="change"/>
<button @click="submit">上传</button>
参数解释
| 参数名 | 意义 |
|---|---|
| multiple | 是否可以一次选择多个文件 |
| type = "file" | 设置后选择文件,可以得到一个 File 对象 |
| $refs.file.value | input 的值为上传文件在本地的绝对地址 |
| @change | 选择的文件发生变化时触发的事件 |
File 对象
前端上传二进制文件就靠这个对象了。如果直接打印File对象可以得到文件名,读取时间大小等信息 ....
特别注意!这些信息都是只读的,不可直接修改。
function change (e) {
// files 数组
const files = e.target.files;
console.log(files)
for (const file of files) {
// file 对象
console.log(file)
}
}
File 对象
File 对象数组
* FileReader 对象
读取 File 对象(文件)的二进制数据
特别注意!FileReader.readAsBinaryString() 方法,我在使用中经常出问题,不建议使用。
function change (e) {
const files = e.target.files;
for (const file of files) {
// 读数据
let fr = new FileReader();
// 读为文本
// fr.readAsText(file)
// 读为图片(Base64编码)
// fr.readAsDataURL(file)
// 读为二进制流
fr.readAsArrayBuffer(file)
// FileReader 对象的事件
// 读取成功
fr.onload = () => {
// 读取到的 ArrayBuffer
console.log(fr.result)
}
// 读取失败
fr.onerror = () => {
alert('Oop!error...')
}
// 读取结束(不管成功还是失败)
fr.onloadend = () => {
console.log('End...')
}
}
}
* Axios 发送 ArrayBuffer 对象
ArrayBuffer 是无法直接发送出去的,需要转换为 Json 对象后发出。
这里提供一个转换函数
function ArrayBufferToJson (arrayBuffer) {
const buffer = new Buffer(arrayBuffer.byteLength);
const view = new Uint8Array(arrayBuffer);
for (let i = 0; i < buffer.length; ++i) {
buffer[i] = view[i];
}
return buffer.toJSON()
}
// 把文件数据和要发给后端的其他信息放入一个对象中
let sendObj = {
uid: 001,
name: ’NiChengKai的测试文件‘,
// 使用上面的函数
data: this.ArrayBufferToJson(fr.result)
}
以 Json 形式发送
由于数据很大,所以只能POST
let {data: res} = await axios.post('后端地址', sendObj, {
headers: {
// 关键
'Content-Type': 'application/json'
}
});
完整代码
html
<input name="file" type="file" multiple/>
<button>上传</button>
js
// 准备发送数据的数组
let sendList = [],
// 结果数组
let resultList = [],
// 转换函数
function ArrayBufferToJson (arrayBuffer) {
const buffer = new Buffer(arrayBuffer.byteLength);
const view = new Uint8Array(arrayBuffer);
for (let i = 0; i < buffer.length; ++i) {
buffer[i] = view[i];
}
return buffer.toJSON()
},
// 选择文件
function change (e) {
const files = e.target.files;
for (const file of files) {
let fr = new FileReader();
fr.readAsArrayBuffer(file)
fr.onload = () => {
let sendObj = {
uid: 001,
name: ’NiChengKai的测试文件‘,
data: ArrayBufferToJson(fr.result)
}
sendList.push(sendObj)
}
fr.onerror = () => {
alert('Oop!error...')
}
fr.onloadend = () => {
console.log('End...')
}
}
}
// 上传
function submit () {
for (const sendObj of sendList) {
let {data: res} = await axios.post('后端地址', sendObj, {
headers: {
'Content-Type': 'application/json'
}
});
resultList.push(res)
}
sendList = [],
// 记得清除 input 的数据
}
后端
后端我使用的是 Node + Express
跨域设置
这是常规,就不多说了
安装
npm install cors -S
引入
// app.js
// 跨域配置
const cors = require('cors');
// noinspection JSCheckFunctionSignatures
app.use(cors({
origin: '*',
optionsSuccessStatus: 200
}));
配置 body-parser 中间件
由于使用了 POST请求 ,需要配置 body-parser 中间件解析 POST请求 的参数。
安装
npm install body-parser -S
引入
// app.js
const bodyParser = require('body-parser');
// 设置解析为 Json 格式并设置数据最大限制
app.use(bodyParser.json({
limit: '40mb'
}))
读取二进制数据
// 需要导入 fs 模块
router.post('/', (req, res) => {
// result 为二进制数据
let {uid, name, result} = req.body;
// 把字符串形式的 Buffer 填充入 Buffer 对象中
result = Buffer.from(result)
// 写文件
fs.writeFile('文件路径', (result, err) => {
if (!err) {
res.send(name + ' 上传成功!')
} else {
res.send(name + '上传失败!')
}
})
})