直击大文件上传的作用

0.效果视频

大文件上传效果演示视频

1.遇到的问题

文件上传: 将用户电脑上的文件上传到服务器的过程(将用户本地的文件拷贝到服务器上)
大文件上传和普通文件上传并没有太大的区别,但是会出现一些很现实问题
	服务器处理数据的能力: 文件过大时,上传文件时会占用服务器过多的内存资源,导致服务器处理能力下降
	请求超时: 文件过大时,上传大文件消耗的时间较多,会导致上传文件请求超时
	网络波动: 网络是不可控的,上传大文件耗时长,如果遇到了网络波动,会导致文件上传失败,还需重新上传

2.技术解决方案

解决思路: 将大文件拆分成多个小文件, 把一个个的小文件进行上传,然后在服务器上合并多个小文件

### 1.分片上传:
	分片上传,就是将所要上传的文件,按照一定的大小,将整个文件分隔成多个数据块(我们称之为 Part)来进行分别上传,上传完之后再由服务端对所有上传的文件进行汇总整合成原始的文件
	前端:将被上传的文件进行切片,给每一片生成唯一标记,并计算总片数
		前端使用 vue 及 spark-md5 技术,获取文件的 md5 值,生成分片文件文件名
    后台:接收前端分片上传的总片数,并分别接收上传的每一片数据文件,上传完毕后,合并上传的每一片数据文件,并删除单片信息
### 2.断点续传:
	分片上传的数据文件,可以暂停上传,后续续传,续传时,根据文件名称,判断每片数据文件是否上传成功且可用,如果可用则忽略本片文件,如果不可用则删除,并续传
### 3.秒传:
	前端选中文件后,服务器端查看是否存在该文件,如果存在直接返回文件已存在(秒传),不存在,继续进行分片上传

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

前端

1.添加依赖

package.json文件中添加大文件上传uploader组件版本依赖

	"vue-simple-uploader": "^0.7.6",

在这里插入图片描述

2.导入组件

在main.js中引用组件

import uploader from 'vue-simple-uploader'
Vue.use(uploader)

在这里插入图片描述

3.页面组件

<template>
  <div>
    <div id="divId">
      <span id="spId">大文件上传</span>
          <uploader :options="options" class="uploader-example" @file-complete="fileComplete" @file-success="successUpload" >
            <uploader-unsupport></uploader-unsupport>
            <uploader-drop>
              <p>将文件放在这里上传</p>
              <uploader-btn>选择上传的文件</uploader-btn>
              <uploader-btn :attrs="attrs">选择上传的图片</uploader-btn>
              <uploader-btn :directory="true">选择上传的文件夹</uploader-btn>
            </uploader-drop>
            <uploader-list></uploader-list>
          </uploader>
    </div>
  </div>
</template>

<script>
export default {
  name: "AskForLeave",
  data() {
    return {
      options: {
        target: 'http://localhost:8888/api/bigfile/postFileUpload', // 目标上传 URL
        chunkSize: '2048000',   //分块大小
        fileParameterName: 'file', //上传文件时文件的参数名,默认file
        maxChunkRetries: 3,  //最大自动失败重试上传次数
        testChunks: false,     //是否开启服务器分片校验
      },
      attrs: {
        accept: 'image/*'
      },
      file:""
    }
  },
  methods: {
    successUpload (rootFile, file, message, chunk) {
      console.log(JSON.parse(message).fileUrl);
      this.file = JSON.parse(message).fileUrl;
    },
    // successUpload(res,data){
    //   debugger
    //   console.log(res);
    //   console.log(data);
    // },
    fileComplete(rootFile) {
      // console.log(rootFile);
    }
  }
}
</script>

<style>
#spId{
  font-size: 40px;
}
#divId{
  width: 30%;
  text-align: center;
  margin:0 auto;
}
html,body,#app{
  margin: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
}
</style>

后台

手动将大文件上传的依赖存放到本地maven仓库: jar包在资料文件夹中

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
       <groupId>com.xiaoxuhaonan.bigfile.uploader</groupId>
        <artifactId>bigfile-upload-spring-boot-starter</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>
spring:
  servlet:
    multipart:
      enabled: true
      max-file-size: 500MB
      max-request-size: 2048MB

  resources:
    static-locations: file:D:/upload
file:
  enable: true
  path: D:/upload/file/
  domain: http://localhost:${server.port}/file/
server:
  port: 8888
package com.baidu.controller;
import com.xiaoxuhaonan.bigfile.uploader.model.Chunk;
import com.xiaoxuhaonan.bigfile.uploader.service.FileService;
import com.xiaoxuhaonan.bigfile.uploader.util.FileResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/api/bigfile")
@CrossOrigin
public class BigFileUploadController {

    @Autowired
    private FileService fileService;
    /**
     * 文件分块上传
     * @param chunk
     * @return
     * @throws InterruptedException
     */
    @RequestMapping("postFileUpload")
    public Object postFileUpload(@ModelAttribute Chunk chunk) throws InterruptedException {
        fileService.postFileUpload(chunk);
        if (chunk.getTotalChunks().equals(chunk.getChunkNumber())) {
            TimeUnit.SECONDS.sleep(2);
            FileResult fileResult = fileService.mergeFile(chunk);
            return fileResult;
        }
        System.out.println("文件上传成功");
        return "success!";
    }
}


效果

前端效果
在这里插入图片描述

后端效果-上传的每一片数据信息
在这里插入图片描述

后端效果-上传完毕后会自动合并数据信息
在这里插入图片描述

源码地址

联系作者: QQ 851900534

Logo

腾讯云面向开发者汇聚海量精品云计算使用和开发经验,营造开放的云计算技术生态圈。

更多推荐