vue文件夹上传-基于vue-simple-uploader简单封装

 

<uploadFolder
   :targetUrl="targetUrl"
   ref="uploader"
    @complete="onFileSuccess"
  />
<template>
    <div>
        <uploader 
            ref="uploader"
            :key="uploader_key"
            @file-added="fileAdded"
            @filesAdded="filesAdded"
            :options="options"
            @file-progress="onFileProgress"
            @file-success="onFileSuccess">
            <uploader-unsupport></uploader-unsupport>
             <uploader-btn 
             v-show="false"
             ref="selectFileBtn"
             id="selectFileBtn"
             :directory="true" 
             :single="true">文件夹</uploader-btn>
        </uploader>
    </div>
</template>
<script>
import { getTno, getToken } from '@/utils/auth';
import FileMd5 from './uploader/common/file-md5';
export default {
    props:{
        targetUrl:{
            type:String,
            default:()=>{
                return '/';
            }
        }
    },
    data(){
        return{
            headers: {
                Authorization: 'Bearer ' + getToken()
            },
            
            uploader_key: new Date().getTime(),
            options: {
            target: this.targetUrl,//SpringBoot后台接收文件夹数据的接口
            testChunks: false,//是否分片-不分片
            headers:this.headers,
            query:{
                tno:getTno()
                }
            },
            filesCount:0,
        }
    },
    created() {
        if (getToken()) {
        this.headers = {
            Authorization: 'Bearer ' + getToken()
        };
        } else {
        this.headers = {};
        }
  },
    methods:{
        onFileSuccess: function (rootFile, file, response, chunk) {
            this.filesCount--;
            if(this.filesCount == 0){
                this.$emit("complete",rootFile, file, JSON.parse(response), chunk);
            }
            this.$refs.uploader.fileRemoved(file);
        //这里可以根据response(接口)返回的数据处理自己的实际问题(如:从response拿到后台返回的想要的数据进行组装并显示)
        //注,这里从文件夹每上传成功一个文件会调用一次这个方法
        this.$emit("on-file-success",rootFile, file, JSON.parse(response), chunk);
        },
        fileAdded(file){
            this.filesCount++;
            FileMd5(file.file, (e, md5) => {
            file.identifier = md5;
            file.status = 1;
          });
          this.$emit("file-added",file);
        },
        filesAdded(files){
        },
        onFileError(rootFile, file, response, chunk) {
            console.log(error)
        },
        onFileProgress(rootFile, file, chunk) {
            console.log(`上传中 ${file.name},chunk:${chunk.startByte / 1024 / 1024} ~ ${chunk.endByte / 1024 / 1024}`)
        },
        fileSelect(){
            if (this.$refs.selectFileBtn) { 
                this.$refs.selectFileBtn.$el.click();
            }
        }
    }
}
</script>

file-md5.js

'use strict';

// import SparkMD5 from './js-spark-md5.js'
import SparkMD5 from 'spark-md5'

export default function (file, callback) {
  // console.log(new SparkMD5.ArrayBuffer())
  var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
    file = file,
    chunkSize = 3145728,                             // Read in chunks of 3MB
    chunks = Math.ceil(file.size / chunkSize),
    currentChunk = 0,
    spark = new SparkMD5.ArrayBuffer(),
    fileReader = new FileReader();
    // console.log(spark)
  fileReader.onload = function (e) {
    // console.log('read chunk nr', currentChunk + 1, 'of', chunks);
    spark.append(e.target.result);                   // Append array buffer
    currentChunk++;

    if (currentChunk < chunks) {
      loadNext();
    } else {
      callback(null, spark.end());
      // console.log('finished loading');
    }
  };

  fileReader.onerror = function () {
    callback('oops, something went wrong.');
  };

  function loadNext() {
    var start = currentChunk * chunkSize,
      end = ((start + chunkSize) >= file.size) ? file.size : start + chunkSize;

    fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
  }

  loadNext();
};

 

controller层

public Result parseBatchDBFile(String filename, String identifier, Long currentChunkSize, Integer totalChunks,
                                    Integer chunkNumber, MultipartFile file,String tno,String relativePath) {
        UploadRspVO uploadRspVO  = null;
        try {
            uploadRspVO = UploadUtils.webUpload(filename,identifier,currentChunkSize,totalChunks,chunkNumber-1,file,relativePath,tno);
        } catch (IOException e) {
            e.printStackTrace();
            return Result.fail("文件上传失败.");
        }
        return Result.ok(uploadRspVO);
    }

UploadUtils

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import java.util.HashMap;
import java.util.Map;


/**
 * 分块上传工具类
 * 记录文件签名
 */
@Component
public class UploadUtils {

    @org.springframework.beans.factory.annotation.Value("${fzhx.file.download}")
    private String download;

    /**
     * 内部类记录分块上传文件信息
     */
    private static class Value {
        String name;
        boolean[] status;

        Value(int n) {
            this.name = generateFileName();
            this.status = new boolean[n];
        }
    }

    private static Map<String, Value> chunkMap = new HashMap<>();

    /**
     * 判断文件所有分块是否已上传
     *
     * @param key 关键字
     * @return 返回了是否上传成功,true表示上传成功
     */
    public static boolean isUploaded(String key) {
        if (isExist(key)) {
            for (boolean b : chunkMap.get(key).status) {
                if (!b) {
                    return false;
                }
            }
            return true;
        }
        return false;
    }

    /**
     * 判断文件是否有分块已上传
     *
     * @param key
     * @return
     */
    private static boolean isExist(String key) {
        return chunkMap.containsKey(key);
    }

    /**
     * 为文件添加上传分块记录
     *
     * @param key
     * @param chunk
     */
    public static void addChunk(String key, int chunk) {
        chunkMap.get(key).status[chunk] = true;
    }

    /**
     * 从map中删除键为key的键值对
     *
     * @param key
     */
    public static void removeKey(String key) {
        if (isExist(key)) {
            chunkMap.remove(key);
        }
    }

    /**
     * 获取随机生成的文件名
     *
     * @param key
     * @param chunks
     * @return
     */
    public static String getFileName(String key, int chunks) {
        if (!isExist(key)) {
            synchronized (UploadUtils.class) {
                if (!isExist(key)) {
                    chunkMap.put(key, new Value(chunks));
                }
            }
        }
        return chunkMap.get(key).name;
    }

    /**
     * 分片上传文件或文件夹(还原目录结构)或不分片
     *
     * @param name   带文件类型的原文件名称
     * @param md5
     * @param size
     * @param chunks
     * @param chunk
     * @param file
     * @param tno    时间戳
     * @return
     * @throws IOException
     */
    public static UploadRspVO webUpload(String name, String md5, Long size, Integer chunks,
                                        Integer chunk, MultipartFile file, String filePath, String tno) throws IOException {

        UploadRspVO uploadRspVO = new UploadRspVO().setSuccess(false).setTno(tno);
        String path = "";
        if (chunks != null && chunks != 0) {
            path = FileUtils.uploadWithBlock(md5, size, chunks, chunk, file);
        } else {
            path = FileUtils.upload(file);
        }

        if (UploadUtils.isUploaded(md5) && chunk == chunks - 1) {

            try {
                //建立临时文件夹
                String tmpSavePath = Paths.get(System.getProperty("user.dir")+"/downloads/").toAbsolutePath().toString();
                FileUtil.mkdir(tmpSavePath);

                //保存到本地的文件路径
                String localFilePath = "";

                //上传类型是文件夹中的文件
                if (StrUtil.isNotBlank(filePath)) {
                    //去掉文件名获取相对路径
                    String uploadFolderPath = StrUtil.removeSuffix(filePath, StrUtil.SLASH + name);
                    //文件保存在本地的路径=临时文件夹加上前端传来的相对路径
                    String localFolderPath = Paths.get(tmpSavePath, uploadFolderPath).toString();
                    FileUtil.mkdir(localFolderPath);
                    localFilePath = Paths.get(localFolderPath, name).toString();

                } else {
                    localFilePath = Paths.get(tmpSavePath, name).toString();
                }

                new File(path).renameTo(new File(localFilePath));
                uploadRspVO.setSavePath(localFilePath).setSuccess(true).setMd5(md5);
            } catch (Exception e) {
                e.printStackTrace();

            } finally {
                if (StrUtil.isNotBlank(path)) {
                    FileUtil.del(path);
                }
            }

        }
        return uploadRspVO;
    }

    /**
     * 分片上传文件或文件夹(还原目录结构)或不分片
     *
     * @param name   带文件类型的原文件名称
     * @param md5
     * @param size
     * @param chunks
     * @param chunk
     * @param file
     * @param tno    时间戳
     * @return
     * @throws IOException
     */
    public  UploadRspVO upload(String name, String md5, Long size, Integer chunks,
                              Integer chunk, MultipartFile file, String tno) throws IOException {

        UploadRspVO uploadRspVO = new UploadRspVO().setSuccess(false).setTno(tno);
        String path = "";
        if (chunks != null && chunks != 0) {
            path = FileUtils.uploadWithBlock(md5, size, chunks, chunk, file);
        } else {
            path = FileUtils.upload(file);
        }

        if (UploadUtils.isUploaded(md5)) {

            try {
                //建立临时文件夹
                String tmpSavePath = Paths.get(download, IdUtil.fastSimpleUUID()).toAbsolutePath().toString();
                FileUtil.mkdir(tmpSavePath);
                String filePath = Paths.get(tmpSavePath, name).toString();
                new File(path).renameTo(new File(filePath));
                uploadRspVO.setSavePath(filePath).setSuccess(true).setMd5(md5);
            } catch (Exception e) {
                e.printStackTrace();

            } finally {
                if (StrUtil.isNotBlank(path)) {
                    FileUtil.del(path);
                }
            }

        }
        return uploadRspVO;
    }
}

UploadRspVO  

import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.experimental.Accessors;

@Data
@Accessors(chain = true)
public class UploadRspVO {
    @ApiModelProperty(value = "是否上传完成")
    private Boolean success;

    @ApiModelProperty(value = "时间戳")
    private String tno;

    @ApiModelProperty(value = "服务器保存文件路径")
    private String savePath;

    @ApiModelProperty(value = "文件夹路径")
    private String folderPath;

    @ApiModelProperty(value = "md5")
    private String md5;

}

 

 FileUtils



import cn.hutool.core.io.FileUtil;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Paths;
import java.util.UUID;


/**
 * 文件操作工具类
 */
public class FileUtils {


//    public static final String PATH = "d:/download/";

    /**
     * 写入文件
     *
     * @param target
     * @param src
     * @throws IOException
     */
    public static void write(String target, InputStream src) throws IOException {
        OutputStream os = new FileOutputStream(target);
        byte[] buf = new byte[1024];
        int len;
        while (-1 != (len = src.read(buf))) {
            os.write(buf, 0, len);
        }
        os.flush();
        os.close();
    }

    /**
     * 分块写入文件
     *
     * @param target
     * @param targetSize
     * @param src
     * @param srcSize
     * @param chunks
     * @param chunk
     * @throws IOException
     */
    public static void writeWithBlok(String target, Long targetSize, InputStream src, Long srcSize, Integer chunks, Integer chunk) throws IOException {
        RandomAccessFile randomAccessFile = new RandomAccessFile(target, "rw");
        randomAccessFile.setLength(targetSize);
        if (chunk == chunks - 1) {
            randomAccessFile.seek(targetSize - srcSize);
        } else {
            randomAccessFile.seek(chunk * srcSize);
        }
        byte[] buf = new byte[1024];
        int len;
        while (-1 != (len = src.read(buf))) {
            randomAccessFile.write(buf, 0, len);
        }
        randomAccessFile.close();
    }

    /**
     * 生成随机文件名
     *
     * @return
     */
    public static String generateFileName() {
        return UUID.randomUUID().toString();
    }

    /**
     * 创建文件
     *
     * @param path
     * @return
     */
    public static File createFile(String path) {
        if (path == null) {
            return null;
        } else {
            File file = new File(path);
            File fileParent = file.getParentFile();
            if (!fileParent.exists()) {
                fileParent.mkdirs();
            }
            return new File(path);
        }
    }


    /**
     * 上传文件
     *
     * @param
     * @param file
     */
    public static String upload(MultipartFile file) throws IOException {
        String generateName = generateFileName();
        String path = Paths.get(System.getProperty("user.dir")+"/downloads/").toAbsolutePath().toString() + generateName;
        File parent = FileUtil.newFile(path).getParentFile();
        if (!parent.exists()) {
            parent.mkdirs();
        }
        FileUtils.write(path, file.getInputStream());
        return path;
    }


    /**
     * 分块上传文件
     *
     * @param md5
     * @param size
     * @param chunks
     * @param chunk
     * @param file
     * @throws IOException
     */
    public static String uploadWithBlock(String md5,
                                         Long size,
                                         Integer chunks,
                                         Integer chunk,
                                         MultipartFile file) throws IOException {
        String fileName = getFileName(md5, chunks);
        String path = Paths.get(System.getProperty("user.dir")+"/downloads/").toAbsolutePath().toString() + fileName;
        FileUtils.writeWithBlok(path, size, file.getInputStream(), file.getSize(), chunks, chunk);
        addChunk(md5, chunk);
        /*if (isUploaded(md5)) {

        }*/
        return path;
    }

    /**
     * 为文件添加上传分块记录
     *
     * @param key
     * @param chunk
     */
    public static void addChunk(String key, int chunk) {
        chunkMap.get(key).status[chunk] = true;
    }

    /**
     * 获取随机生成的文件名
     *
     * @param key
     * @param chunks
     * @return
     */
    public static String getFileName(String key, int chunks) {
        if (!isExist(key)) {
            synchronized (UploadUtils.class) {
                if (!isExist(key)) {
                    chunkMap.put(key, new Value(chunks));
                }
            }
        }
        return chunkMap.get(key).name;
    }
}

相关推荐

  1. vue文件夹-基于vue-simple-uploader简单封装

    2024-01-12 15:08:01       35 阅读
  2. vue 分布式文件vue-simple-uploader

    2024-01-12 15:08:01       14 阅读
  3. vue3中组件upload简单使用

    2024-01-12 15:08:01       26 阅读
  4. vue2 upload多图片

    2024-01-12 15:08:01       17 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-01-12 15:08:01       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-01-12 15:08:01       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-01-12 15:08:01       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-01-12 15:08:01       20 阅读

热门阅读

  1. 响应式编程WebFlux基础实战练习

    2024-01-12 15:08:01       30 阅读
  2. C++的内存管理模型

    2024-01-12 15:08:01       36 阅读
  3. Transformer学习(一)

    2024-01-12 15:08:01       40 阅读
  4. mybatis&Mysql 分页查询

    2024-01-12 15:08:01       39 阅读
  5. 算法习题练习

    2024-01-12 15:08:01       29 阅读
  6. .net core 6 集成和使用 mongodb

    2024-01-12 15:08:01       36 阅读
  7. 【大数据面试】常见数仓建模面试题附答案

    2024-01-12 15:08:01       33 阅读
  8. vue3知识盲点总结

    2024-01-12 15:08:01       30 阅读