文件上传及文件相关操作

前端文件上传有两种方式

二进制blob通过formData传输和转为base64传输

前端文件上传涉及到四种文件对象

files:通过input标签度过来的文件对象,前端对象不能传给后端

vue
1234567
<input type="file" name="file" @change="fileChage"/>

<script>
	fileChage(e){
        console.log(e.target.files[0])//files对象是自己创建好的,是一个数组,如果是单文件上传就是第0项
    }
</script>

以下是对上传的文件进行文件类型与大小的限制方法

vue
123456789
<input type="file" name="file" @change="fileChage"/>

<script>
	fileChage(e){
        let file = e.target.files[0]
        if(file.size > 10 * 24 * 24)alert("文件不能大于十兆")
        if(file.type !== 'video/mp4')alert("文件必须是mp4")
    }
</script>

blob:不可变的二进制内容,包含很多操作方法

fileReader:多用与把文件读取为某种形式,如base64,text文本

vue
1234567891011121314
<input type="file" name="file" @change="fileChage"/>
<script>
	fileChage(e){
        let file = e.target.files[0]
        let blob = new Blob([file])//将file对象转为blob对象
        let _sliceBlob = blob.slice(0,5000)//对blob进行切割
        let _sliceFile = new File([_sliceBlob],"fileName.png")//将切割后的blob转为file
        let fr = new FileReader()
        fr.readAsDataURL(_sliceFile)//将切割后的文件转成base64
        fr.onload = function() {//由于FileReader是异步执行的所以需要在这里面使用
            console.log(fr.result)
        }
    }
</script>

注:缩略图功能就是将base64的图片展示出来,文本预览也是使用FileReader做

formData:用于和后端传输的对象

vue
123456789101112131415
<input type="file" name="file" @change="fileChage"/>
<button @click="submit">提交</button>
<script>
    let _fileObj
	fileChage(e){
        let file = e.target.files[0]
 		_fileObj = file
    }
    const submit = () => {//由于formdata的作用主要是用来传递给后端,所以在提交的时候进行转换即可
        let _formData = new FormData()
        _formData.append("user","abcabc")//在给后端的信息中添加一个字段叫user,值为abcabc
        _formData.append("file",_fileObj)//在给后端的信息中添加一个字段叫file,值为_fileObj
        axios.post("/xx.com",_formData)//发送给后端
    }
</script>

以上实现的就是单文件上传

文件的转化关系如下

781d05a6460b5b6aa0e68ef177f19023.png

多文件上传

原理就是将多个文件一个一个发送请求给后端

vue
1234567891011121314151617181920212223
//加上multiple属性支持一次选择多个文件,但是用户体验不好,所以我们需要在js中对其进行一些操作
<input type="file" name="file" @change="fileChage" multiple/>
<button @click="submit">提交</button>
<script>
    let imgList = [];
    let _fileObj;
	fileChage(e){
        if(e.target.files.lenth > 1){
            imgList = imgList.concat(e.target.files)//当添加的文件数大于1的时候就将数组与之前的添加的拼接
        }else{
            imgList.push(e.target.files[0])//当添加的文件数只有1的时候就直接push
        }
 		_fileObj = file
    }
    const submit = () => {//由于formdata的作用主要是用来传递给后端,所以在提交的时候进行转换即可
        imgList.forEach((item) => {//遍历数组,将文件转为FormData
            let _formData = new FormData()
            _formData.append(item.name,item)
            axios.post("/xx.com",_formData)//发送给后端
        })
        
    }
</script>

切片上传

原理:将大文件切成多片再转成formdata形式传给后端

vue
12345678910111213141516171819202122232425
<input type="file" name="file" @change="fileChage"/>
<div>{{ precent }}</div>//文件上传进度展示
<button @click="submit">提交</button>

<script>
    let _fileObj
    let precent //用来展示文件上传进度
	fileChage(e){
        let file = e.target.files[0]
 		_fileObj = file
    }
    const submit = () => {
        let size = 2 * 1024 * 1024 //每片大小2Mb
        let fileSize = _fileObj.size
        let current = 0 //当前切到位置的基准值
        while(current < fileSize){//只要还没切完就继续
            let _formData = new FormData()
            //每次发送2Mb的切片给后端
        	_formData.append(_fileObj.name,_fileObj.silce(current,current + size))
            await axios.post("xxx.com",_formData)
            precent = Math.min((current / fileSize) * 100, 100)//上传进度
            current += size
        }
    }
</script>

后端方面:判断传过来的文件名一致,就拼接起来