【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));
    }

}
相关推荐
冷琴19969 分钟前
基于java+springboot的酒店预定网站、酒店客房管理系统
java·开发语言·spring boot
九圣残炎32 分钟前
【springboot】简易模块化开发项目整合Redis
spring boot·redis·后端
.生产的驴1 小时前
Electron Vue框架环境搭建 Vue3环境搭建
java·前端·vue.js·spring boot·后端·electron·ecmascript
老齐谈电商1 小时前
Electron桌面应用打包现有的vue项目
javascript·vue.js·electron
琴智冰1 小时前
SpringBoot
java·数据库·spring boot
LIURUOYU4213081 小时前
vue.js组建开发
vue.js
爱码少年1 小时前
springboot工程中使用tcp协议
spring boot·后端·tcp/ip
九圣残炎1 小时前
【Vue】vue-admin-template项目搭建
前端·vue.js·arcgis
《源码好优多》2 小时前
基于SpringBoot+Vue+Uniapp的植物园管理小程序系统(2024最新,源码+文档+远程部署+讲解视频等)
vue.js·spring boot·uni-app
计算机学姐2 小时前
基于微信小程序的调查问卷管理系统
java·vue.js·spring boot·mysql·微信小程序·小程序·mybatis