• 关于elementt的upload图片上传标签的解读,上传视频。上传大文件切片——生成一个哈希值,Message的消息提示。


    <el-upload 
        action="https://jsonplaceholder.typicode.com/posts/"
        提交图片的服务器地址
        :on-preview="handlePreview" 
        :on-remove="handleRemove" 
        :before-remove="beforeRemove" 
        以上是三个事件
    	 multiple
    	 这个意思是上传多张
        :limit="3" 
        限制最多上传几张
        :on-exceed="handleExceed" 
        :file-list="fileList"
        两个事件
        >
        
        <el-button size="small" type="primary">点击上传el-button>
        <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kbdiv>
    el-upload>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这里暂且用的到的有:

    头像图片上传

    这样写就是一次传一个。

    <el-upload action="" :on-change="changeHandle">
    	<el-button size="small" type="primary">点击上传头像el-button>
    	<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kbdiv>
    el-upload>
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述

    属性说明类型
    on-change文件状态改变时的钩子,添加文件、上传成功和上传失败时都会被调用function(file, fileList)

    这个函数里的参数一就是我上传的一个头像文件file对象

    changeHandle(response) {
        console.log(response);
    }
    
    • 1
    • 2
    • 3

    在这里插入图片描述
    可以看出对象的类型Wie:File。那么如何将file上传到服务器呢,
    把File对象传到服务器

    得到对象:里面的row对象。
    changeHandle(response) {
    	console.log(response);
    	const formData = new FormData()
    	formData.append('file', response.raw)
    },
    
    ++++++++++++++++分割线解读++++++++++++++++++
    
    const formData = new FormData();
    给forData这种Map类型添加一个属性file::file.row。
    formData.append('file', response.raw);
    
    然后直接将表单对象传输上去:
    
    let ret = await uploadAvatar(formData);
    uploadAvatar:封装好的ajax,服务器去解析。
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    上传视频

    nodejs搭建服务器,然后设置一个公共资源路径,请求数据返回一个路径

    // 设置静态资源目录
    app.use(express.static('./public'))//目录下面有视频
    app.post("/msg",(req,res)=>{
        console.log("我post被访问了");
        res.send({
            code:Date.now(),
            data:"http://localhost:4000/niu.mp4"
        })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    客户端
    el-upload标签自带一个axaj。

    <el-upload action="http://localhost:4000/msg" 
    	:on-success="uploadSuccess"
    	:show-file-list="false">
    		<el-button size="small" type="primary">点击上传视频</el-button>
    </el-upload>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    在这里插入图片描述
    :on-success事件:上传成功后返回其响应内容;

    uploadSuccess(response){//参数就是一个响应体。
        console.log(response);
    }
    
    • 1
    • 2
    • 3

    当选择一个视频上传完可以在控制台查看其返回响应,状态如何。
    在这里插入图片描述
    但是这种写法有好有坏。方便维护,不利于安全。

    大文件上传——方案

    那么遇到超大文件,或者比较大的文件的时候该怎么传:

    有个on-change属性,上面就是说过,第一个参数就是传输的文件本身。

    • 对于文件较大的文件上传进行分片上传,把一个大文件,拆分成若干个小的文件,然后再上传。
    • 切成小的方案
        1. 指定大小,然后来切文件 大小固定,数量不定
        1. 指定数量,然后来切文件,数据固定,大小不定
    • 上传时,要有一个编号,这样在服务器端才能根据此编号完成文件的合并操作
    • 还需要根据文件的内容,生成一个根据内容来得到的一个唯一随机字符串,此字符串一定要和内容是关联,只要内容有变化,则随机字符串要有变化,如果内容没有变化,则字符串不变(hash字符串[hash值])
    • 如果你没有此hash值,这样有可能在上传过来中,如果有两个相同的文件,就会上传两次,不太好
    • 有hash值,在合并的时候,可以用此hash值,来当作合并后的文件名称

    hash值_0.mp4
    hash值_1.mp4
    hash值_2.mp4
    ==> hash值.mp4 完整的文件

    <el-upload action="http://localhost:4000/msg" 
    :on-success="uploadSuccess"
    :show-file-list="false"
    :on-change="changeHandle">
    	<el-button size="small" type="primary">点击上传视频</el-button>
    </el-upload>
    
    *******
    methods:
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    得到切片的大小:
    当前的索引值是多少:

    changeHandle(file){
        if(!file) return
        console.log(file.raw.size);
        let partnum = 4;//切片数
        console.log(file.raw.size/partnum);//每一块的大小
        let currentIndex = 0;//当前的索引值是多少
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    生成一个哈希值

    在线MD5生成https://www.sojson.com/md5/
    在这里插入图片描述

    安装一个插件包,给定内容生成一个哈希值(加密稳定)

    安装
    npm i -S spark-md5
    导入
    import SparkMd5 from "spark=md5" 
    给定一个内容生成一个md5.
    
    • 1
    • 2
    • 3
    • 4
    • 5

    要把内容转成哈希值之前,先要把内容转为arrayBuffer对象。buffer二进制数据流。把得到的buffer数据流转为一个hash值。

    const read = new FileReader();/* 一个类的实例对象 */
    read.readAsArrayBuffer(file.raw);/* 将file.raw转为arraybuffer */
    read.onload = evt=>console.log(evt.target.result);
    
    • 1
    • 2
    • 3

    封装成一个函数:(异步)

    async changeHandle(file){
                if(!file) return
                console.log(file.raw.size);
                let partnum = 4;//切片数
                console.log(file.raw.size/partnum);//每一块的大小
                let currentIndex = 0;//当前的索引值是多少
                let result = await this.binary(file.raw,"arraybuffer");//生成arraybuffer数据流
                console.log(result);
            },
    binary(fileobj,type='binary'){
        return new Promise((resolve,reject)=>{
            const read = new FileReader();
            if(type == 'binary'){
                read.readAsBinaryString(fileobj);//普通二进制数据流(照片啥的)
            }else{
                read.readAsArrayBuffer(fileobj);//arraybuffer类数据流(大文件,视频啥的)
            }
            read.onload = evt=>resolve(evt.target.result);//返回最终的生成结果
        })
    },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    在这里插入图片描述


    把得到的buffer数据流计算出来一个hash值

    根据文件内容得到一个hash字符串,当做切片的前缀。得到文件扩展名。

    let spark = new SparkMd5.ArrayBuffer();
    spark.append(result)//把buffer的结果以流的形式填充进去的
    let hash = spark.end();//结束的话返回一个字符串
    console.log("hash:",hash);
    // 得到一个文件的拓展名
    let extName = file.raw.name.split(".").pop();
    console.log(extName);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    在这里插入图片描述

    切片存储:

    // 存储切好的文件,数组
    let partList = [];
    for(let i=0;i<partnum;i++){
        let chunk = file.raw.slice(currentIndex,partSize);//文件切片
        partList.push({
            filename:`${hash}_${i}.${extName}`,
            chunk:chunk
        })
        currentIndex += partSize;
    }
    console.log(partList);
    
    this.partList = partList;
    this.hash = hash;
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    在这里插入图片描述

    将生成的多个小文件,串行按序请求网络。

    let requertList = [];//存储每一个异步请求方法
    partList.forEach(({filename,chunk})=>{
        const requestFn = ()=>{
            return new Promise((resolve,reject)=>{
                setTimeout(() => {
                    resolve(filename)
                }, 1000);
            })
        };
        requertList.push(requestFn);
    })
    /*串行执行方法,每一个每一个的执行*/
    let index = 0;
    const next =async ()=>{
        if(index>=requertList.length){
            console.log("传输完成");
            return;
        }
        let name = await requertList[index++]();
        console.log(name);
        next();
    }
    next();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    通过表单对象,上传切片的文件。

    partList.forEach(({filename,chunk})=>{
    	const requestFn =async ()=>{
    	const formData = new FormData();
    		formData.append("filename",filename);
    		formData.append("chunk",chunk);
    		let msg = await post("http://10.9.46.247:4000/msg",formData);
    		console.log("msg:",msg);
    	};
    
    	requertList.push(requestFn);
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    在这里插入图片描述


    Message的消息提示

    this.$message("上传失败");
    this.$message.error("上传失败");
    this.$message.success("上传成功");
    
    • 1
    • 2
    • 3
    <template>
        <el-container>
            <el-header>Headerel-header>
            <el-container>
                <el-aside width="200px">
                    <Enmu />
                el-aside>
                <el-container>
                    <el-main>
                        <el-breadcrumb separator="/">
                            <el-breadcrumb-item :to="{ path: '/' }">首页el-breadcrumb-item>
                            <el-breadcrumb-item><a href="/">活动管理a>el-breadcrumb-item>
                            <el-breadcrumb-item>活动列表el-breadcrumb-item>
                            <el-breadcrumb-item>活动详情el-breadcrumb-item>
                        el-breadcrumb>
                        <el-input placeholder="请输入内容" clearable class="shuru">
                        el-input>
                        <el-button type="primary">点击搜索el-button>
                        <el-button type="success">添加信息el-button>
                        <el-button type="danger">删除选中el-button>
                        <el-divider>el-divider>
    
    
                        <el-form ref="form" :model="form" label-width="80px">
                            <el-form-item label="账号" prop="input">
                                <el-input v-model="form.input"  />
                            el-form-item>
    
                            <el-form-item label="上传头像">
                                <el-upload action="" :on-change="changeHandle">
                                    <el-button size="small" type="primary">点击上传头像el-button>
                                    <div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kbdiv>
                                el-upload>
                            el-form-item>
                            <el-form-item label="上传视频">
                                <el-upload action="http://localhost:4000/msg" 
                                :on-success="uploadSuccess"
                                :show-file-list="false"
                                :on-change="changeHandle">
                                    <el-button size="small" type="primary">点击上传视频el-button>
                                el-upload>
                                <el-divider>el-divider>
                                <video v-if="src" :src="src"  width="200px" height="300px"  controls poster="https://gimg2.baidu.com/image_search/src=http%3A%2F%2Fp3.itc.cn%2Fq_70%2Fimages01%2F20210619%2Fa7afb11dcd09419a911da798e6aa8878.png&refer=http%3A%2F%2Fp3.itc.cn&app=2002&size=f9999,10000&q=a80&n=0&g=0n&fmt=auto?sec=1666056532&t=3b092bbb7b19927dd0b2e1ee4e93463d">video>
                            el-form-item>
                            <el-button type="success" @click="submitForm('form')">点击上传el-button>
                        el-form>
    
                        
                    el-main>
                    <el-footer>Footerel-footer>
                el-container>
            el-container>
        el-container>
    
    template>
    
    <script>
    import Bn from "@/components/Btcm.vue"
    import Enmu from "@/views/menu"
    import SparkMd5 from 'spark-md5'
    import {post} from "@/utils/http"
    export default {
        name: "upload",
        components: {
            Bn, Enmu
        },
        data() {
            return {
                src:'',
                form: {
                    input: '123'
                }
            };
        },
        methods: {
            // changeHandle(response) {
            //     // console.log(response);
            //     const formData = new FormData()
            //     formData.append('file', response.raw)
            // },
            submitForm(formName) {
                this.$refs[formName].validate((valid) => {
                    if (valid) {
                        console.log(this.$refs[formName]);
                        console.log("aaaaa");
                        console.log(this.$refs[formName]._props.model.input);
                        // this.$refs[formName].resetFields()
                        // alert('submit!');
                    } else {
                        console.log('error submit!!');
                        return false;
                    }
                });
            },
            resetForm(formName) {
                
                this.$refs[formName].resetFields();
               
            },
            async changeHandle(file){
                if(!file) return
                console.log(file.raw.size);
                let partnum = 4;//切片数
                console.log(file.raw.size/partnum);//每一块的大小
                let partSize = file.raw.size/partnum;
                let currentIndex = 0;//当前的索引值是多少
                /* 获得一个哈希值 */
    
                // const read = new FileReader();/* 一个类的实例对象 */
                // read.readAsArrayBuffer(file.raw);/* 将file.raw转为arraybuffer */
                // read.onload = evt=>console.log(evt.target.result);/*异步过程,输出二进制数据流 */
                let result = await this.binary(file.raw,"arraybuffer");
                console.log(result);
                
                let spark = new SparkMd5.ArrayBuffer();
                spark.append(result)//把buffer的结果以流的形式填充进去的
                let hash = spark.end();//结束的话返回一个字符串
                console.log("hash:",hash);
                // 得到一个文件的拓展名
                let extName = file.raw.name.split(".").pop();
                console.log(extName);
                // 存储切好的文件,数组
                let partList = [];
                for(let i=0;i<partnum;i++){
                    let chunk = file.raw.slice(currentIndex,partSize);//文件切片
                    partList.push({
                        filename:`${hash}_${i}.${extName}`,
                        chunk:chunk
                    })
                    currentIndex += partSize;
                }
                console.log(partList);
                this.partList = partList;
                this.hash = hash;
    
                let requertList = [];
    
                partList.forEach(({filename,chunk})=>{
                    const requestFn =async ()=>{
                        const formData = new FormData();
                        formData.append("filename",filename);
                        formData.append("chunk",chunk);
                        let msg = await post("http://10.9.46.247:4000/msg",formData);
                        console.log("msg:",msg);
                    };
                    requertList.push(requestFn);
                })
                let index = 0;
                const next =async ()=>{
                    if(index>=requertList.length){
                        console.log("传输完成");
                        return;
                    }
                    let name = await requertList[index++]();
                    console.log(name);
                    next();
                }
                next();
    
    
    
            },
            binary(fileobj,type='binary'){
                return new Promise((resolve,reject)=>{
                    const read = new FileReader();
                    if(type == 'binary'){
                        read.readAsBinaryString(fileobj);//普通二进制数据流(照片啥的)
                    }else{
                        read.readAsArrayBuffer(fileobj);//arraybuffer类数据流(大文件,视频啥的)
                    }
                    read.onload = evt=>resolve(evt.target.result);//返回最终的生成结果
                })
            },
            uploadSuccess(response){
                // console.log(response);
                this.src = response.data;
            },
    
            
        }
    
    }
    script>
    <style>
    
    style>
    <style>
    .el-header,
    .el-footer {
        background-color: #B3C0D1;
        color: #333;
        text-align: center;
        line-height: 60px;
    }
    
    .el-aside {
        background-color: #D3DCE6;
        color: #333;
        text-align: center;
        line-height: 200px;
    }
    
    /* 
    .el-main {
        background-color: #E9EEF3;
        color: #333;
        text-align: center;
        line-height: 160px;
    } */
    
    body>.el-container {
        margin-bottom: 40px;
    }
    
    .el-container.is-vertical {
        height: 730px;
    }
    
    .el-container:nth-child(5) .el-aside,
    .el-container:nth-child(6) .el-aside {
        line-height: 260px;
    }
    
    .el-container:nth-child(7) .el-aside {
        line-height: 320px;
    }
    
    .shuru {
        margin-top: 15px;
        width: 300px
    }
    
    .el-button {
        margin-left: 20px;
    }
    style>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
  • 相关阅读:
    为什么说区块链的性能难以衡量?
    RABC权限模型与Spring Security
    JavaScript复习笔记 (十二)jQuery
    如何在Linux中转换一个/Home目录到分区
    PHP分类信息网站源码系统 电脑+手机+微信端三合一 带完整前后端部署教程
    jsp库存管理系统Myeclipse开发mysql数据库web结构java编程计算机网页项目
    基于Java的长整数加减法算法设计
    ApDBUtils引出、土方法完成封装
    难点解释-理解寄主机通过虚拟网络连接到虚拟机的概念
    软考135-上午题-【软件工程】-软件配置管理
  • 原文地址:https://blog.csdn.net/m0_46672781/article/details/126909273