前言
最近遇到了一个需要处理文件上传的需求,趁这个机会顺便把前端的一些文件处理做下总结
浏览器上的文件
HTML上传文件,一般是通过
<input type="file" />
input
设置type="file"
,html页面就会自动生成一个按钮,可以选择文件上传。
vue来测试input上传文件
我们用vue中的ref来获取input上的元素
<input type="file" ref="fileInput" />
<button @click="checkFile">check file</button>
export default {
name: 'HelloWorld',
data() {
return {
msg: 'Welcome to Your Vue.js App'
}
},
methods: {
checkFile() {
console.log(this.$refs.fileInput.files)
}
}
}
输出情况
我们来上传文件看看,浏览器保存的文件格式是怎么样的。
我们在MDN上可以查询到这个file
对象的信息
通过MDN上的信息,了解到这个file
有:
- size:文件大小
- name:文件名称
- lastModified:修改时间
- webkitRelativePath 这个好像是webkit还在研发的端口,它保存的是文件的路径,目前支持度不是很高,所以这里为空
- type:文件类型
其实这里的file对象已经提供了非常详细的数据了,我们可以通过这些数据来自定义一些上传的验证和格式化。
自定义校验
对文件格式、大小进行校验
很多框架就已经封装了一些检验的API,一般配置好一些属性就能够达到校验的要求。
原生的写法:在input
上绑定onchange
事件,函数的第一个参数的target
就是input
DOM元素,输出DOM上的file
就可以获取到上传文件对象,然后再去验证file
上的文件数据进行验证。
checkFile() {
let file = this.$refs.fileInput.files[0]
console.log(this.$refs.fileInput.files)
let limitSize = 1 * 1024 * 1024 // 1MB大小限制
if (limitSize < file.size) {
console.log('超过1MB限制')
} else {
console.log('文件上传')
}
}
验证文件格式
checkFile() {
let file = this.$refs.fileInput.files[0]
console.log(this.$refs.fileInput.files)
let type = 'image/jpeg'
if (type !== file.type ) {
console.log('请上传jpg文件')
} else {
console.log('文件上传')
}
}
当然也可以多文件格式验证
checkFile() {
let file = this.$refs.fileInput.files[0]
console.log(this.$refs.fileInput.files)
let type = ['image/jpeg','imges/png']
for(let item of type ){
if (type === file.type ) {
console.log('文件上传')
}
}
console.log('请上传正确格式文件')
}
后台需要的数据
一般后台需要的数据是file
对象,因为这个对象中有一个隐式的属性值保存着文件上传的路径。
在使用一些UI框架的时候会将它封装到raw
属性下。
上传的方式一般是使用formdata
上传。
nodejs
使用express
可以使用body-parse
进行解析。
使用multer
处理files
文件解析
const express = require('express')
// 处理formdata
const bodyParser = require('body-parser')
const app = express()
// 处理file文件
var multer = require('multer')
// 设置文件上传的路径
var upload = multer({ dest: 'uploads/' })
// 跨域
var allowCors = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
res.header('Access-Control-Allow-Headers', 'Content-Type')
res.header('Access-Control-Allow-Credentials', 'true')
next()
}
app.use(allowCors)
app.use(
bodyParser.urlencoded({
extended: true
})
)
app.use(bodyParser.json())
app.use(upload.any())
app.post('/file', (req, res) => {
let formData = req.body
console.log(req.files)
console.log('form data', formData)
res.status(200).send(formData)
})
app.listen(8555, () => console.log('Example app listening on port 8555!'))
测试
前端
我们使用前端页面进行上传
前端的请求会携带文件和我们自定义的名字
后台
文件上传的输出
文件会自动处理到req.files
这一个数组上,上面有文件的各种信息。
formdata
也可以看到我们携带的信息
我们需要对上传的文件进行适当的处理,比如修改文件名字。
我们可以使用multer
具备的文件上传前置回调函数
// 设置文件处理
var storage = multer.diskStorage({
destination: function(req, file, cb) {
// 设置保存的路径
cb(null, path.join(__dirname, '../uploads'))
},
filename: function(req, file, cb) {
// 保存文件名字
cb(null, `${Date.now()} - ${file.originalname}`)
}
})
// 设置处理的函数
var upload = multer({ storage })
传入的file
对象
保存的文件
后台代码
const express = require('express')
// 处理formdata
const bodyParser = require('body-parser')
const app = express()
const path = require('path')
// 处理file文件
var multer = require('multer')
// 设置文件处理
var storage = multer.diskStorage({
destination: function(req, file, cb) {
// 设置保存的路径
cb(null, path.join(__dirname, '../uploads'))
},
filename: function(req, file, cb) {
// console.log('storage', file, cb)
cb(null, `${Date.now()} - ${file.originalname}`)
}
})
// 设置处理的函数
var upload = multer({ storage })
// 跨域
var allowCors = function(req, res, next) {
res.header('Access-Control-Allow-Origin', '*')
res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS')
res.header('Access-Control-Allow-Headers', 'Content-Type')
res.header('Access-Control-Allow-Credentials', 'true')
next()
}
app.use(allowCors)
app.use(
bodyParser.urlencoded({
extended: true
})
)
app.use(bodyParser.json())
app.use(upload.any())
app.post('/file', (req, res) => {
let formData = req.body
console.log(req.files)
console.log('form data', req.files, formData)
res.status(200).send(formData)
})
app.listen(8555, () => console.log('Example app listening on port 8555!'))