前言
最近遇到了一個需要處理文件上傳的需求,趁這個機會順便把前端的一些文件處理做下總結
瀏覽器上的文件
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!'))