【vue + springboot】切片+断点上传 + 秒传

需要了解透彻请参考:如何实现大文件上传、断点续传、切片上传_断点上传-CSDN博客

说明

切片:根据指定的大小对文件进行切块上传。

断点上传:每次上传完成一个切片后端保存信息,前端每次上传都判断所上传的文件是否存在,存在后端则返回信息,前端再根据信息进行调整继续上传。

秒传:如果文件已经在后端中存在,直接返回上传成功。可以节磁盘,提高用户体验,这里我用的是文件名来判断,不推荐,一般使用hash或者算法来为文件取一个唯一标识。

前端

axiosFun.sj

没有安装axios就在命令行安装:npm install axios

import axios from 'axios';

const req = (method, url, params) => {

    return axios({

        method: method,

        url: url,

        data: params,

        headers: {

            'Content-Type': 'multipart/form-data',

        },

        traditional: true,

    }).then(res => res.data);

};

const jsonReq = (method, url) => {

    return axios({

        method: method,

        url: url,

        traditional: true,

    }).then(res => res.data);

};

export { req, jsonReq };

request.js

import { req, jsonReq } from "./axiosFun";

export const upload = (params) => req('post', '/test/upload', params)

export const getUploadFile = (params) => jsonReq('get', '/test/getUploadFile/' + params)

type.js

class FileChunk {

  constructor(chunk, fileName, start, end, total) {

    // 切片对象

    this.chunk = chunk;

    // 文件名称

    this.fileName = fileName;

    // 切片起始位置

    this.start = start;

    // 切片结束位置

    this.end = end;

    // 文件总大小

    this.total = total;

  }

}

export default FileChunk;

 HelloWorld.vue

<template>

  <el-upload class="upload-demo" ref="upload" action="https://jsonplaceholder.typicode.com/posts/" :file-list="fileList"

    :on-change="selectFile" :auto-upload="false" :limit="max_fileNum" :on-exceed="onExceed">

    <el-button slot="trigger" size="small" type="primary">选取文件</el-button>

    <el-button style="margin-left: 10px;" size="small" type="success" @click="submitUpload">上传到服务器</el-button>

  </el-upload>

</template>

<script>

import FileChunk from './type.js';

import { upload, getUploadFile } from './request.js';

export default {

  name: 'FileChunk',

  data() {

    return {

      fileList: [],

      max_fileNum: 1,

      fileChunkSize: 10240

    };

  },

  methods: {

    createFileChunkList(start, end_) {

      let fileChunkList = [];//文件块list

      let file = this.fileList[0];//文件

      let cur = null;//文件切割当前位置

      let end = null;//文件切割结尾位置

      //断点续传

      if (start != null && end_ != null) {

        let temp = start + this.fileChunkSize;

        if (temp < file.size) {

          cur = temp;

        }

        end = cur + this.fileChunkSize

        if (end >= file.size) {

          end = file.size

        }

        //从头开始切片上传

      } else {

        cur = 0;

        end = this.fileChunkSize

      }

      //当前文件小于切块文件,直接返回

      if (file.size < this.fileChunkSize) {

        return fileChunkList.push(new FileChunk(file, file.name, cur, file.size));

      } else {

        //断点续传已切到最后一块

        if (end == file.size) {

          let blob = new Blob([file]).slice(cur, end);

          const fileChunk = new FileChunk(blob, file.name, cur, end, file.size);

          fileChunkList.push(fileChunk);

        }

        //切片

        while (end < file.size) {

          let blob = new Blob([file]).slice(cur, end);

          const fileChunk = new FileChunk(blob, file.name, cur, end, file.size);

          fileChunkList.push(fileChunk);

          let temp = cur + this.fileChunkSize;

          if (temp < file.size) {

            cur = temp;

          }

          end = cur + this.fileChunkSize

          if (end >= file.size) {

            end = file.size

          }

        }

      }

      //返回切片list

      return fileChunkList;

    },

    //上传

    submitUpload() {

      let fileChunkList = null;

      //判断是否是断点上传的文件

      getUploadFile(this.fileList[0].name).then(res => {

        if (res.data == null) {//文件不存在,直接传

          fileChunkList = this.createFileChunkList(null, null);

        } else if (res.data.end == res.data.total) {//该文件已经存在了 -> 秒传

          this.$message.success("上传成功")

          return;

        } else {//断点,文件续传

          fileChunkList = this.createFileChunkList(res.data.start, res.data.end);

        }

        let reqNum = 0;//请求次数

        let errCount = 3;//只允许错误三次

        while (reqNum < fileChunkList.length && errCount > 0) {

          const formData = new FormData();

          formData.append("file", fileChunkList[reqNum].chunk);

          formData.append("fileChunk", JSON.stringify(fileChunkList[reqNum]));

          upload(

            formData

          ).then(res => {

            if (res) {

              reqNum += 1;

            } else {

              errCount -= 1;

            }

            this.$message.success(res.data.msg)

          });

        }

      })

    },

    selectFile(file) {

      this.fileList.push(file.raw)

    },

    onExceed() {

      this.$message.error("一次只能上传一个文件");

    }

  }

}

</script>./type.js

后端

操作数据库所需要的实体类、接口、mapper参考type.js创建一个表格,代码生成即可

返回值直接拷贝:CSDN

package com.example.demo.controller;import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.demo.domain.FileChunk;
import com.example.demo.res.R;
import com.example.demo.service.FilechunkService;
import lombok.AllArgsConstructor;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;import java.io.RandomAccessFile;@RestController
@RequestMapping("/test")
@AllArgsConstructor
public class FileUploadController {private static final String UPLOAD_DIR = "D:\\luo\\code\\demo3\\src\\main\\resources\\files\\";private final FilechunkService filechunkService;@PostMapping("/upload")public R uploadFileChunk(@RequestParam("file") MultipartFile file, @RequestParam("fileChunk") String fileChunk) {FileChunk f = JSONUtil.toBean(fileChunk, FileChunk.class);String fullPath = UPLOAD_DIR + f.getFileName();// 模块写入对应的位置,rw表示读写模式try (RandomAccessFile rf = new RandomAccessFile(fullPath,"rw")) {rf.seek(f.getStart());rf.write(file.getBytes());} catch (Exception e) {return R.fail(e.getMessage());}//存储信息,一般存放在redis中,并设置在一定的时间内删除f.setId(1L);filechunkService.updateById(f);return R.success("上传成功");}@GetMapping("/getUploadFile/{name}")public R followUpload(@PathVariable("name") String name) {//查询数据库的信息,继续上传QueryWrapper<FileChunk> wrapper = new QueryWrapper<>();wrapper.eq("file_name", name);return R.data(filechunkService.getOne(wrapper));}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/794534.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

纪念品分组

题源 贪心做法 &#xff0c;先排序再分组 题目描述 元旦快到了&#xff0c;校学生会让乐乐负责新年晚会的纪念品发放工作。为使得参加晚会的同学所获得 的纪念品价值相对均衡&#xff0c;他要把购来的纪念品根据价格进行分组&#xff0c;但每组最多只能包括两件纪念品&#xff…

1.9 面试经典150题 除自身以外数组的乘积

除自身以外数组的乘积 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0…

vue如何搭建项目?

首先我们下载安装router&#xff0c;less / scss&#xff0c;pinia&#xff0c;axios&#xff0c; element / Ant Design Vue&#xff0c;Echarts 以及如何配置别名&#xff0c;自定义组件 npm npm create vitelatest yarn yarn create vite 然后安装依赖 成功后 在src下…

PyTorch搭建Informer实现长序列时间序列预测

目录 I. 前言II. InformerIII. 代码3.1 输入编码3.1.1 Token Embedding3.1.2 Positional Embedding3.1.3 Temporal Embedding 3.2 Encoder与Decoder IV. 实验 I. 前言 前面已经写了很多关于时间序列预测的文章&#xff1a; 深入理解PyTorch中LSTM的输入和输出&#xff08;从i…

python 笔记

文章目录 pdbpdb开始调试pythonpdb设置断点单步执行进入到函数的内部执行到下一个断点或程序结束调用栈查看命令查看当前函数调用堆栈向上一层函数查看调用堆栈查看源代码 importimport 用法 numpy导入numpy模块numpy常用函数np.argmaxnp.sum range生成连续序列生成不连续序列 …

离线数仓(十)【ADS 层开发】

前言 剩下的 ADS 层主要就是写 SQL 了&#xff0c;就像我们之前练习的 HQL 题一样&#xff0c;不同的是这里的数据从哪张表读取&#xff08;DWD 还是 ADS 甚至个别表需要从 DIM 层读取&#xff09;需要我们自己来分析。 ADS 的建表语句和 MySQL 是对应的&#xff0c;我们到时候…

从0到1实现RPC | 04 负载均衡和静态注册中心

一、Router的定义 Router路由用于预筛选&#xff0c;Dubbo有这样的设计&#xff0c;SpringCloud没有。 二、LoadBanlancer定义 负载均衡器&#xff1a;默认取第一个 当前支持随机和轮询两种负载均衡器。 随机&#xff1a;从所有provider中随机选择一个。 轮询&#xff1a;每…

【C++】引用与指针

​​ &#x1f331;博客主页&#xff1a;青竹雾色间. &#x1f618;博客制作不易欢迎各位&#x1f44d;点赞⭐收藏➕关注 ✨人生如寄&#xff0c;多忧何为 ✨ 目录标题 前言一.引用&#xff08;Reference&#xff09;二.指针&#xff08;Pointer&#xff09;三. 比较与总结 前…

面试题:Spring Boot Starter的功能与使用场景

Spring Boot Starter 是 Spring Boot 框架为了简化项目的初始化和配置工作而设计的一种模块化依赖管理方式。它主要具有以下几个关键功能和使用场景&#xff1a; 功能&#xff1a; 1. 依赖管理每个 Starter 都是一组相关的依赖项集合&#xff0c;这些依赖项都是为了实现特定功能…

机器学习第33周周报Airformer

文章目录 week33 AirFormer摘要Abstract一、论文的前置知识1. 多头注意力机制&#xff08;MSA&#xff09;2. 具有潜变量的变分模型 二、文献阅读1. 题目2. abstract3. 问题与模型阐述3.1 问题定义3.2 模型概述3.3 跨空间MSA&#xff08;DS-MSA&#xff09;3.4 时间相关MSA&…

【Qt 学习笔记】使用两种方式实现helloworld

博客主页&#xff1a;Duck Bro 博客主页系列专栏&#xff1a;Qt 专栏关注博主&#xff0c;后期持续更新系列文章如果有错误感谢请大家批评指出&#xff0c;及时修改感谢大家点赞&#x1f44d;收藏⭐评论✍ 使用两种方式实现helloworld 文章编号&#xff1a;Qt 学习笔记 / 05 …

C语言数据结构专题--顺序表(1基础)

前言 我们在对C语言有一定的了解之后&#xff0c;我们就可以开始数据结构的学习了&#xff0c;数据结构多用指针、结构体、动态内存开辟等知识&#xff0c;若对这些知识还不太了解的朋友&#xff0c;就需要加深其理解了&#xff0c;那么废话不多说&#xff0c;我们正式开始本节…

Web攻击越发复杂,企业如何保护云上业务

如今&#xff0c;电子政务、电子商务、网上银行、网上营业厅等依托Web应用&#xff0c;为广大用户提供灵活多样的服务。在这之中&#xff0c;流量攻击堪称是Web应用的最大敌人&#xff0c;黑客通过流量攻击获取利益、竞争对手雇佣黑客发起恶意攻击、不法分子通过流量攻击瘫痪目…

约数与倍数-第12届蓝桥杯选拔赛Python真题精选

[导读]&#xff1a;超平老师的Scratch蓝桥杯真题解读系列在推出之后&#xff0c;受到了广大老师和家长的好评&#xff0c;非常感谢各位的认可和厚爱。作为回馈&#xff0c;超平老师计划推出《Python蓝桥杯真题解析100讲》&#xff0c;这是解读系列的第45讲。 约数与倍数&#…

用html写一个爱心

<!DOCTYPE html> <html lang"zh-CN"><head><meta http-equiv"Content-Type" content"text/html; charsetUTF-8" /><title>爱您</title><style>* {padding: 0;margin: 0;}body {background-color: pin…

【软件测试】测试常见知识点汇总

测试常见知识点汇总 一、什么是测试1.1 测试和调试的区别1.2 什么是需求1.2.1 用户需求1.2.2 软件需求 1.3 测试用例要素1.4 软件的生命周期及各阶段概述1.5 开发模型和测试模型&#xff08;记住特点和适用场景&#xff09;1.5.1 开发模型1.5.1.1 瀑布模型&#xff08;自上而下…

WebKit结构详细简介

第一章:WebKit概述 WebKit是一个开源的网页浏览引擎,最初由苹果公司为其Safari浏览器开发,后来成为了多个浏览器的基础,包括苹果的Safari、Google的Chrome、微软的Edge等。它不仅在桌面端有着广泛的应用,还被广泛地应用于移动端的浏览器中,如iOS和Android系统。WebKit的…

vue3+element-plus(el-carousel)实现图片轮播和点击预览功能

解决的问题&#xff1a;默认的插件在点击预览图片时&#xff0c;总是从第一张图片开始显示&#xff0c;而不是当前点击的这一张&#xff0c;于是便做了下面的优化&#xff0c;使用js记录当前点击图片的索引&#xff0c;再进行预览。 <template><el-carousel indicato…

armlinux-外部中断

s3c2440的中断框图 如果我们单纯配置一个按键的外部中断&#xff0c;就不存在子中断与优先级的问题。 由于是按键的外部中断&#xff0c;通过引脚的高低电平来触发。所以我们要先配置引脚的功能。 我们使用按键1&#xff0c;终端源为EINT8&#xff0c;对应引脚GPG0 通过用户手…

java中大型医院HIS系统源码 Angular+Nginx+SpringBoot云HIS运维平台源码

java中大型医院HIS系统源码 AngularNginxSpringBoot云HIS运维平台源码 云HIS系统是一款满足基层医院各类业务需要的健康云产品。该产品能帮助基层医院完成日常各类业务&#xff0c;提供病患预约挂号支持、病患问诊、电子病历、开药发药、会员管理、统计查询、医生工作站和护士工…