文件上传组件
需要提前掌握
input file
html
<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png" capture="camera" multiple />
作用
该组件在界面的表现形式是一个上传按钮,点击该组件会打开文件选择弹窗,选择了文件之后,这个上传按钮会显示文件名称
事件
change 事件
通过 change 事件就能获取到用户选择的文件的文件对象
html
<input
ref="realUploadFileBtnRef"
type="file"
class="realUploadFileBtn"
accept="image/gif,image/jpeg,image/jpg,image/png"
@change="onGetFile"
/>
ts
function onGetFile(e: Event) {
// 获取文件上传按钮的dom实例
const inputDom = e.target as HTMLInputElement
if (!inputDom) return
// 获取用户选择的所有文件
const files = inputDom.files
if (!files) return
// 如果未指定 multiple 属性,则一次只能选择一个文件,使用 files[0] 即可获取到,如果指定了 multiple 属性,则需要循环 files 数组
const imageFile = files[0]
// 这里可以进行真正的文件类型判断
console.log(imageFile)
// 因为 accept 并不能真正意义上的禁止用户选择某类文件,这里获取到的文件类型,也不能完全保证正确,因此前端就做到 accept 控制下即可,严格的文件类型校验,还是留给后端吧
console.log(imageFile.type)
// size属性能够获取到文件大小
console.log(imageFile.size)
const picInfo: PicInfo = {
_id: `${new Date().getTime()}-${++seed}`,
// 这里能够获取到文件名
name: imageFile.name,
}
// 每次change事件最后都要将文件上传按钮的value值设置为空字符,不然,下次再选择同一个文件,将无法再触发change事件
inputDom.value = ''
convertImgToBase64(imageFile, (base64: string) => {
picInfo.url = base64
picInfo.id = picInfo._id
val.value = picInfo
emitTrigger()
})
}
/**
* 将图片转成base64格式
*
* @param imageFile 图片文件
* @param callback 转成成功函数回调(这里是接收转换成功结果的函数)
* @param errorCallback 转成失败函数回调(这里是接收转换失败结果的函数)
*/
function convertImgToBase64(imageFile: File, callback: (base64: string) => void, errorCallback?: (error: any) => void) {
try {
let reader = new FileReader()
reader.onload = function (ev: ProgressEvent<FileReader>) {
if (callback) {
const fileReader = ev.target
if (!fileReader) {
errorCallback && errorCallback('图片转base64失败')
return
}
let base64Str = fileReader.result as string
callback(base64Str)
}
}
reader.readAsDataURL(imageFile)
} catch (error) {
console.error(error)
if (errorCallback) {
errorCallback(error)
}
}
}
属性说明
capture
调用设备媒体。在 webapp 上使用 input 的 file 属性,指定 capture 属性可以调用系统默认相机、摄像和录音功能。
capture 表示,可以捕获到系统默认设备的媒体信息,如下:
capture="camera" 相机
capture="camcorder" 摄像机
capture="microphone" 录音
html
<input type="file" accept="image/*" capture="camera" />
<input type="file" accept="video/*" capture="camcorder" />
<input type="file" accept="audio/*" capture="microphone" />
multiple
设置了该属性之后,将支持多文件选择
accept
设置 input file 默认选择的文件类型。当我们打开系统的选择文件弹框的时候,默认界面中呈现的文件类型。通过使用 accept 属性限制文件类型,如果想支持多种类型的话,只要在 accept 里面放置多个属性就可以了(逗号隔开)。
选择 JSON 文件
html
<input id="file1" type="file" accept=".json" />
选择图片文件
html
<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png" />
选择文档文件
html
<input id="file1" type="file" accept=".xls,.doc,.txt,.pdf" />
WARNING
accept 值支持通配符,如:<input id="file1" type="file" accept="image/*"/>, 但这有可能造成Webkit内核下打开文件弹窗缓慢的问题,因此尽量不要使用这种形式的通配符,而是要指定所有的类型.像这样:<input type="file" accept="image/gif,image/jpeg,image/jpg,image/png">
accept 属性并不会验证选中文件的类型,只是为开发者提供了一种引导用户做出期望行为的方式,用户还是有办法绕过浏览器的限制。 因此,在服务器端进行文件类型验证还是很有必要的。
axios 实现文件上传
单文件上传
js
async handleUploadFile(event) {
const file = event.target.files[0]
let formData = new FormData()
formData.append('files', file)
formData.append('test', '其他参数')
const res = await service({
url: '/api/files/upload',
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data'
},
data: formData
})
console.log(res.data);
}
多文件上传
html
<input id="upload_file" type="file" multiple @change="v_upload_files" />
js
v_upload_files(e) {
let files = e.target.files
let formData = new FormData()
// formData重复的往一个值添加数据并不会被覆盖掉,可以全部接收到,可以通过formData.getAll('files')来查看所有插入的数据
for (let i = 0;i < files.length;i++) {
formData.append('files', files[i])
}
formData.append('test','其他参数')
let url = '/files/uploadfiles'
let headers = {
'Content-Type': 'multipart/form-data'
}
axios.post(url, formData, {headers: headers})
}
上传的文件类型校验
accept 并不能完全禁止用户上传的实际文件类型,可以在文件选择框中,选择*/*即可绕过 accept 的限制,还可以将其他类型的文件的后缀改为 accept 支持的类型,所以单纯的 accept 属性,是没法完全限制住的. change 事件中可以获取到 file 对象,file 对象有 type 属性,这里也能拿到文件类型,但也无法完全保证准确。还可以通过二进制判断,但对前端而言,检查二进制就有点复杂了,同时检查二进制也有很多坑。因此个人认为前端上传文件类型检查,限制下 accept,检查下文件名的后缀即可。不必做复杂的校验.
如下文章,有讲解 JS 通过文件的二进制内容判断文件类型
前端——利用 File signature 精准校验文件类型
如果一定要通过二进制检查,来进行文件类型判断,可以考虑使用第三方组件来实现检查
参考资料
HTML5 - 限制 input file 可选择的文件类型