前端
大致流程如下
- 我们使用vue提供的ref属性来获得<input type=“file”>标签的dom对象
- 该dom对象的files属性数据类型为FileList,为input的文件信息
- 遍历FileList,得到File对象,使用FileReader读取File对象,获得该文件的ArrayBuffer对象
- 把ArrayBuffer对象转换为数组,使用post请求发送给后端。(题外话:后端拿到ArrayBuffer对象也能保存文件,但很怪的一点是,如果这里把ArrayBuffer对象直接塞到post参数里,后端会收到一个空对象,但很明显ArrayBuffer并不是一个空对象。所以这里我先把他转换为数组,然后把数组送到后端。)
<template>
<label><input type="file" ref="input" multiple>文件</label>
<button @click="submit">提交文件</button>
</template>
<script lang="ts" setup>
import {ref} from 'vue'
import axios from 'axios'
const input = ref<any>()
function submit(){
const files = input.value.files as FileList
for(let i = 0; i < files.length; i++){
const file = files[i]
const fileReader = new FileReader()
fileReader.readAsArrayBuffer(file)
fileReader.onload = () => {
const arrayBuffer = Array.from(new Uint8Array(fileReader.result as ArrayBuffer))
axios.post('http://localhost:9000/submitFile', {fileName:file.name, arrayBuffer:arrayBuffer})
.then(() => {console.log(file.name + '上传成功')})
}
}
}
</script>
服务端
服务端流程就比较简单了,值得注意的有两点,一是解析body的中间件body-parser默认有大小限制100kb,当大小超过100kb就会报错,我们要手动去设置这个上限;二是注意fs.writeFile()的使用,它的第二个参数接受一个Buffer数据类型,注意Buffer.from()的用法,他的参数是字符串,缓冲区,数组或arrayBuffer。
const express = require('express')
const cors = require('cors')
const fs = require('fs')
const bodyParser = require('body-parser')
const app = express()
app.use(cors())
app.use(bodyParser.urlencoded({
extended: false,
limit: '50mb'
}))
app.use(bodyParser.json({limit: '50mb' }))
const basePath = './'
app.post('/submitFile', (req, res) => {
fs.writeFile(basePath + req.body.fileName, Buffer.from(req.body.arrayBuffer), error => {
console.log(error)
})
})
app.listen(9000)
更规范化的文件上传
前端使用FormData
上面的方式是自己瞎摸索的,我网上搜了下很少有人那样传文件,而且如果使用第三方云端存储库的话,比如网上的图床和对象存储云服务,它们提供的api也不支持那样的传输方式。
更加规范的文件上传方式应该是将File对象传递给后端,但上面已经说了,直接把File对象粗鲁地塞到post参数里是不行的,我们要使用FormData对象来构建请求参数,使用formData.append()方法把file对象加到参数里,文件的内容会以二进制的形式添加到请求参数中。同时要把请求头的’Content-Type’字段设置为 ‘multipart/form-data’,一些第三方的ajax库如axios会自动帮我们做这种设置。
formData.append("fieldname", file, file.name)
axios.post('/upload', formData)
后端express使用中间件multer
multer基本使用方法如下:
const express = require('express')
const cors = require('cors')
const app = express()
app.use(cors())
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, __dirname)
},
filename: function (req, file, cb) {
let indexOfPoint = file.originalname.lastIndexOf('.')
let fileExtention = file.originalname.slice(indexOfPoint)
if(indexOfPoint === -1){
fileExtention = ''
}
let filename = new Date().getTime() + fileExtention
cb(null, filename)
}
})
const upload = multer({ storage: storage});
app.post('/submitFile', upload.single("fieldname"), (req, res) => {
res.end(JSON.stringify({name: req.file.filename, path: req.file.path}))
})
app.listen(9000)
|