文件上传

问题描述:项目里需要上传1G以上的iso文件,不使用插件
解决方法:

<template>
    <div class="file-panel">
        <!-- -->
        <input type="file" id="file" ref="uploadBtn"  accept=".iso"/>
        <div>
            <div class="file-list">
                <ul>
                    <li class="file-item" v-for="(file,index ) in fileList" :key="index">
                        <span
                            style="margin-right:30px;white-space:nowrap;text-overflow:ellipsis;overflow:hidden;font-size:14px;width:280px"
                        >{{file.name}}</span>
                        <span style="margin-right:10px;font-size:14px">{{file.size}}G</span>
                        <span style="margin-right:15px;font-size:14px">{{file.date}}</span>
                        <a title="移除" @click="remove(file,index)">
                            <i class="el-icon-delete"></i>
                        </a>
                        <el-progress :percentage="percentage[index]"></el-progress>
                    </li>
                </ul>
            </div>
        </div>
        <!-- <button id="upload" @click="upload">上传</button> -->
    </div>
</template>

<script>
 import SparkMD5 from 'spark-md5';
export default {
    data() {
        return {
            index: -1,
            shardSize: 2 * 1024 * 1024, //以2MB为一个分片
            dataBegin: null, //开始时间
            dataEnd: null, //结束时间
            action: false,
            fileList: [], //存放文件的名称、上传文件的时间和上传进度
            percentage: [],
            md5:''
        };
    },
    methods: {
        //点击按钮
        upload() {
            this.dataBegin = new Date();
            let file = document.getElementById("file").files[0];
            let start = parseInt(start, 10) || 0;
            let end = parseInt(end, 10) || (file.size - 1);
            this.isUpload(file);
         console.log('点击我,上传呀')
        },
        //删除文件
        remove(file, index) {
            console.log('我被删除了')
            this.fileList.splice(index, 1);
        },
        //MD5值
        computeMD5(file){
            var running=false
            if (running) {
                return;
            }
            //这里需要用到File的slice( )方法,以下是兼容写法
            var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
                //file = input.files[0],
                chunkSize = 2097152,                           // 以每片2MB大小来逐次读取
                chunks = Math.ceil(file.size / chunkSize),
                currentChunk = 0,
                spark = new SparkMD5(),    //创建SparkMD5的实例
                time,
                fileReader = new FileReader();

                let promise = new Promise((reslove, reject) => {
                    fileReader.onload = function (e) {
                        spark.appendBinary(e.target.result);                 // append array buffer
                        currentChunk += 1;
                        if (currentChunk < chunks) {
                            loadNext();
                        } else {
                            running = false;
                            console.log("Finished loading!");
                           
                            reslove(spark.end())
                        }
                    };
                    fileReader.onerror = function () {
                        running = false;
                        reject()
                    };
                })
                
                
                function loadNext() {
                    var start = currentChunk * chunkSize,
                        end = start + chunkSize >= file.size ? file.size : start + chunkSize;
 
                    fileReader.readAsBinaryString(blobSlice.call(file, start, end));
                }
 
                running = true;
                loadNext();

                return promise
        },
        //检查是否上传
        isUpload(file) {
          
            let self =this
            let flag=true
            let form = new FormData(); //构造一个表单,FormData是HTML5新增的
            this.computeMD5(file)
            .then(res => {
                let md5 = res
                this.$http.post("/virtualDrive/isUpload", {
                    md5: md5
                })
                .then(({ data }) => {
                    let uuid = data.fileId;
                    let date = data.date;
                    if (data.flag == "0") {
                        //没有上传过文件
                         this.UpLoad(file, uuid, md5, date);
                    } else if (data.flag == "1") {
                        //已经上传部分文件
                       this.UpLoad(file, uuid, md5, date);
                    } else if (data.flag == "2") {
                        //已经上传过文件
                        this.$message.success("文件已经上传过,秒传了!!");
                    }
                });
            })
            .catch(err => {
                // 获取MD5失败
                this.$message.warn('失败')
            })
        },
        //上传文件
        UpLoad(file, uuid, md5, date) {
            let name = file.name;
            let size = file.size;
            let shardCount = Math.ceil(size / this.shardSize); //总片数
            if (this.index > shardCount) {
                return;
            } else {
                if (!this.action) {
                    this.index += 1; //只有在检测分片时,i才去加1; 上传文件时无需加1
                }
            }
            //计算每一片的起始与结束位置
            var start = this.index * this.shardSize;
            var end = Math.min(size, start + this.shardSize);
            //构造一个表单,FormData是HTML5新增的
            var form = new FormData();
            if (!this.action) {
                form.append("action", "check"); //检测分片是否上传
            } else {
                form.append("action", "upload"); //直接上传分片
                form.append("data", file.slice(start, end)); //slice方法用于切出文件的一部分
            }
            form.append("uuid", uuid);
            form.append("md5", md5);
            form.append("date", date);
            form.append("name", name);
            form.append("size", size);
            form.append("total", shardCount); //总片数
            form.append("index", this.index + 1); //当前是第几片
            let index = this.index + 1;
            //按大小切割文件段
            let data = file.slice(start, end);
            let r = new FileReader();
            r.readAsArrayBuffer(data);
 

            r.onload = e => {
                let spark = new SparkMD5.ArrayBuffer()
                spark.append(e.target.result);
                let partMd5= spark.end();
                form.append("partMd5", partMd5);
                //文件 把数字格式化为指定的长度
                let fileSize = parseFloat(file.size / 1024 / 1024 / 1024).toPrecision(2);

                //去重
                let [mark, fileIndex] = [false, 0];
                this.fileList.forEach((item, i) => {
                    if (item.name == file.name) {
                        mark = true;
                        fileIndex = i;
                    }
                });

                if (!mark) {
                    this.fileList.push({
                        name: file.name,
                        date: this.dataBegin.Format("HH:mm:ss"),
                        size: fileSize
                    });
                    this.percentage.push(
                        Number(((index / shardCount) * 100).toFixed(2))
                    );
                } else {
                    let val = Number(((index / shardCount) * 100).toFixed(2));
                    val = Number(val) > 100 ? 100 : Number(val);
                    this.$set(this.percentage, fileIndex, val);
                }

                this.$http
                    .post("/virtualDrive/upload", form, {
                        headers: {
                            "Content-Type": "multipart/form-data"
                        }
                    })
                    .then(({ data }) => {
                        console.log("上传接口");

                        let fileuuid = data.fileId;
                        let flag = data.flag;

                        if (flag == "2") {
                            this.$message.success("上传成功!");
                        } else if (flag != "2") {
                            //服务器返回该分片是否上传过
                            if (flag == "0") {
                                //未上传,继续上传
                                this.action = true;
                            } else if (flag == "1") {
                                //pending状态
                                this.action = false;
                            }
                            this.UpLoad(file, uuid, md5, date);
                        }
                    });
            };
        }
    },
    computed: {},
    mounted() {
        this.$eventBus.$on("upload", () => { //父组件的按钮使用
            this.upload(); 
        });
    },
    watch: {}
};
</script>
<style lang="stylus" scoped>
.file-panel
    width 100%
    margin-top 10px
.file-list
    height 160px
    max-height 160px
    overflow-y auto
    margin-top 20px
.file-item
    height 50px
    line-height 50px
    padding 0 10px
    background-color #fff
    z-index 1
    display inline-block
    border-bottom 1px solid #ccc
    display flex
    flex-direction row
    flex 1
.progress
    width 200px
    height 20px
    margin-left 30px
</style>
<style lang="stylus">
.file-panel
    .el-progress
        margin-top 15px
        margin-left 30px
    .el-progress-bar__outer
        height 0 !important
</style>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值