Web前端文件上传,单文件、多文件、分段切片上传

前言

文件上传是必须要掌握的,上传文件这里不说原理了,一般都是把拿到的文件转化为base64或者blob二进制传送给后端,主要用到前端的input标签中type属性中的file。

单文件、多文件上传

因为单文件和多文件上传的原理都是一样的,所以会一个另一个也就会了,这是为了方便使用的是vue外部引用没有使用脚手架

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>多文件上传</title>
</head>

<body>
    <div id="app">
        <input type="file" name="file" multiple @change="fileChange">
        <span v-for="item in fileList">{{item.name}}</span>
        <div v-for="item in imgbase64">
           <img :src="item" alt="">
        </div>
        <button @click="onsubmit">提交文件</button>
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    new Vue({
        el: '#app',
        data: {
            fileList: [], //多文件上传存储
            imgbase64: [], //多文件转为base64位
        },
        methods: {
            fileChange(e) {
                console.log(e.target.files);
                //把所有上传的图片文件转化为base64显示在页面上
                let file = e.target.files[0]
                //创建文件读取对象 异步的
                let fr = new FileReader();
                let that = this;
                //readAsDataURL方法会将获取的文件转化为base-64字符串
                fr.readAsDataURL(file)
                //监听页面刷新也就是有文件上传了就把这个文件添加到imgbase64数组中
                fr.onload = function () {
                    that.imgbase64.push(fr.result)
                }
                //多文件上传 判断当前文件的个数是否大于1,如果大于1说明是多文件就让文件数组和自己定义的fileList数组拼接,如果文件数量不大于1就直接把文件添加进去               
                if (e.target.files.length > 1) {
                //这个地方用拼接是因为,我们上传的文件会存在一个对象里面的数组中,图片我放在下面了
                    this.fileList.concat(e.target.files)
                } else {
                    this.fileList.push(e.target.files[0])
                }
            },
            async onsubmit() {
                //因为上传的文件是file类型不能直接发给后端需要用FormData当作载体传送
                let that = this;
                console.log(that.fileList);
                that.fileList.forEach(item => {
                    let _formData = new FormData()
                    _formData.append(item.name + 'file', item);
                    //这里直接发送请求
                    // axios.post()
                });
            }
        },
    })
</script>

</html>

Web前端文件上传,单文件、多文件、分段切片上传_第1张图片
我们可以看到我们上传的文件本获取到以后是一个对象,对象里面有各种属性,我们文件内容就存放在e.target.files这个里面,有很多教程说多文件上传只需要给input设置 一个multiple就可以的,但是这样在选择上传文件的时候如果想选择多个文件需要按住 Ctrl+鼠标点击,如果不这样还是一次只能点击一个,毕竟大多数用户都不懂技术,所以我们要全面考虑。

分割切片上传

这中方式是考虑到文件太大,一次上传需要很长时间造成卡顿,或则我们需要一个进度条来显示文件上传的进度,
思路:把获取到的文件进行转成base64字符串,我们设定一个每次上传的大小,使用slice里面参数设置为自己定义的么欸此上传的大小。请看代码注释写的很清楚

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>切片上传</title>
</head>

<body>
    <div id="app">
        <input type="file" name="file" multiple @change="fileChange">
        <button @click="onsubmit">提交文件</button>
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
<script>
    let _fileObject;
    new Vue({
        el: '#app',
        data: {
            baifenbi:'',//上传的百分比
        },
        methods: {
            fileChange(e) {
            //这个地方是让每次上传的文件按对象都是一个,方便后面使用
                _fileObject = e.target.files

            },
            async onsubmit() {
                //大文件进行切割上传
                let size=2*1024*1024;//每次上传多少
                let fileSize=_fileObject.size;//文件的总大小
                let current=0;//上传的大小
                localStorage.setItem(_fileObject.name.current);
                //这个存储到本地是为了断点续传,上传中断了,记录中断的位置,下次继续上传
                while (current<fileSize) {//当上传的大小小于总文件大小就继续上传
                //创建一个FormDate对象用来当作载体运输我们的文件传给后端
                    let _formData=new FormData()
                    //第一个参数是 上传的文件名字 第二个是每次截取多少文件上传
                    let sliceFile=_formData.append(_fileObject.name,_fileObject.slice(current,current+size))
                    //发送请求
                    await axios.get('请求地址',sliceFi)
                    //做一个百分进度条
                    this.baifenbi=Math.min((current/fileSize)*100,100).toFixed(0)
                    current+=size;
                }

            }
        },
    })
</script>
</html>

总结

文件上传很重要,项目中总会遇到文件上传,方法千千万,适合自己最重要

你可能感兴趣的:(前端,javascript,vue.js)