使用webuploader组件实现大文件分片上传,断点续传

使用webuploader组件实现大文件分片上传,断点续传_第1张图片
无组件断点续传.gif
1. 组件简介

webuploader:是一个以HTML5为主, Flash为辅的文件上传组件,采用大文件分片/并发上传的方式,极大地提高了文件上传的效率,同时兼容多种浏览器版本;

2. 项目背景简介

本篇文章的背景,是在上一篇文章(《无组件实现大文件分片上传,断点续传》)的项目背景下进行的一次尝试,所以本篇文章还是基于上一篇文章的背景,但是不会介绍视频基本信息(视频标题、简介、播出时间等)的操作,主要介绍文件的上传。因为项目的特殊需求,这种使用插进的方式最终没有被采用,因为一些控件无法做到定制化。
上一篇文章(《无组件实现大文件分片上传,断点续传》)中介绍的文件上传方式,在前端主要采用纯JavaScript来进行文件切分、验证,后台主要采用了NIO的方式进行分片的追加。而在这篇文章中,将介绍前端采用webuploader,后台采用临时目录+传统I/O方式进行分片合并的方式。

3. 技术实现
3.1 组件引入

在webuploader官网下载必要的文件,放入项目中。在页面中进行引入;

使用webuploader组件实现大文件分片上传,断点续传_第2张图片
0_组件引入.png



3.2 前端页面实现

在前端页面中,可以不用关心css样式,但需要注意标签的id/nama属性,这些将在后面的JavaScript中使用到。

使用webuploader组件实现大文件分片上传,断点续传_第3张图片
1-页面实现.png

    
可以一次上传多个大文件
选择文件
开始上传
暂停上传
3.3 使用组件实现文件的上传、切分、发送

在这部分,将使用组件完成文件上传、MD5验证、删除、切片、上传进度条显示、暂停、继续上传及上传成功/失败时候的回调。

使用webuploader组件实现大文件分片上传,断点续传_第4张图片
无组件断点续传.gif

以上为前端代码的实现

3.4 后台分片接收

在后台分片接收部分,主要是判断文件是否有分片,如果没有,则直接存放到目的目录;如果存在分片,则创建临时目录,存放分片信息;之后判断当前分片所属的文件的所有分片是否已经传输完毕,如果当前分片数==所属文件总分片数,则开始合并文件并转移完整文件到目的目录,并且删除临时目录;
如下图,是上传文件时所创建的临时目录及目录中的临时文件;

2-临时目录.png
使用webuploader组件实现大文件分片上传,断点续传_第5张图片
3-临时文件.png

Controller实现

/**
     * 
     * @Description: 
     *          接受文件分片,合并分片
     * @param guid   
     *          可省略;每个文件有自己唯一的guid,后续测试中发现,每个分片也有自己的guid,所以不能使用guid来确定分片属于哪个文件。
     * @param md5value
     *          文件的MD5值
     * @param chunks
     *          当前所传文件的分片总数
     * @param chunk
     *          当前所传文件的当前分片数
     * @param id
     *          文件ID,如WU_FILE_1,后面数字代表当前传的是第几个文件,后续使用此ID来创建临时目录,将属于该文件ID的所有分片全部放在同一个文件夹中
     * @param name
     *          文件名称,如07-中文分词器和业务域的配置.avi
     * @param type
     *          文件类型,可选,在这里没有用到
     * @param lastModifiedDate 文件修改日期,可选,在这里没有用到
     * @param size  当前所传分片大小,可选,没有用到
     * @param file  当前所传分片
     * @return
     * @author: xiangdong.she
     * @date: Aug 20, 2017 12:37:56 PM 
     */
    @ResponseBody
    @RequestMapping(value = "/BigFileUp")
    public String fileUpload(String guid, String md5value, String chunks, String chunk, String id, String name,
            String type, String lastModifiedDate, int size, MultipartFile file) {
        String fileName;
        JSONObject result=new JSONObject();
        try {
            int index;
            String uploadFolderPath = FileUtil.getRealPath(request);

            String mergePath = uploadFolderPath + "\\fileDate\\" + id + "\\";
            String ext = name.substring(name.lastIndexOf("."));

            // 判断文件是否分块
            if (chunks != null && chunk != null) {
                index = Integer.parseInt(chunk);
                fileName = String.valueOf(index) + ext;
                // 将文件分块保存到临时文件夹里,便于之后的合并文件
                FileUtil.saveFile(mergePath, fileName, file, request);
                // 验证所有分块是否上传成功,成功的话进行合并
                FileUtil.Uploaded(md5value, guid, chunk, chunks, mergePath, fileName, ext, request);
            } else {
                SimpleDateFormat year = new SimpleDateFormat("yyyy");
                SimpleDateFormat m = new SimpleDateFormat("MM");
                SimpleDateFormat d = new SimpleDateFormat("dd");
                Date date = new Date();
                String destPath = uploadFolderPath + "\\fileDate\\" + "video" + "\\" + year.format(date) + "\\"
                        + m.format(date) + "\\" + d.format(date) + "\\";// 文件路径
                String newName = System.currentTimeMillis() + ext;// 文件新名称
                // fileName = guid + ext;
                // 上传文件没有分块的话就直接保存目标目录
                FileUtil.saveFile(destPath, newName, file, request);
            }

        } catch (Exception ex) {
            ex.printStackTrace();
            result.put("code", 0);
            result.put("msg", "上传失败");
            result.put("data", null);
            return result.toString();
        }
        result.put("code", 1);
        result.put("msg", "上传成功");
        return result.toString();
    }

3.5文件I/O操作实现

此部分代码较多,已将FileUtil上传至Batatas项目下的Util目录(喜欢Batatas这个项目的小伙伴,别忘了点个star哟,或者也非常欢迎加入我们),在这部分实现中,主要用到了一下几个方法:

  • saveFile()//保存分片至临时目录,或者保存未拆分文件到目标目录;
  • mergeFile()//合并临时目录中的临时文件,并将合并后的文件转移至目标目录;
  • saveStreamToFile()//使用I/O流合并分片文件
  • getSavePath()//获取文件保存的路径,如果没有该目录,则创建,可用于临时目录或目标存放目录的创建;
  • isAllUploaded()//在fileUtil中,使用一个全局的uploadInfoList去存放,已经上传的分片信息;在合并分片之前,首先回去这个List中检查属于该文件的所有分片信息是否已经存在,如果不存在,则不合并;如果已全部存在,则将这些信息从list中删除,并开始合并分片;
4. 总结

本篇文章主要介绍了使用百度Webuploader组件进行大文件的分片上传、断点续传,以及服务器端分片合并与转移。

你可能感兴趣的:(使用webuploader组件实现大文件分片上传,断点续传)