大文件的分片传,断点续传,md5校验

首先是前台代码:

1、html文件

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title>文件上传</title>
        <script type="text/javascript" src="/js/jquery.js"></script>
        <script type="text/javascript" src="/js/spark-md5.js"></script>
        <script type="text/javascript" src="/js/myUpload.js"></script>
        <link rel="stylesheet" href="/css/bootstrap.min.css" />
        <style>
            body{
                padding:10px;
            }
            .upload,.progress{
                display:inline-block;
                vertical-align: middle;
                margin:0;
            }
        </style>
    </head>


    <body>
        <input id="isPause" value="1" style="display: none"/>
        <input id="hashcode" value="" style="display: none"/>
        <input id="temphashcode" value="" style="display: none"/>
        <input id="tempFileName" value="" style="display: none"/>
        <input id="fileName" value="" style="display: none"/>
        <div id="cont">
            <div class="upload">
                <button type="button" id="upload"  class="btn btn-primary">选择文件</button>
                <button type="button" id="isPauseButton" class="btn btn-primary" >暂停</button>
                <input id="myupload" type="file" style="display:none;" />
                <div id="uploadProgress"></div>
            </div>

        </div>
    </body>
</html>

 2、css文件,使用bootstrap 
 

3、js文件,使用spark-md5.js

 
 
/**
 * Created by lxg on 2016/12/20.
 */

/**
 * 文件对象
 */
var fileObj = {
    upLoadSize : 0
};

/**
 * 上传配置
 */
var opt = {
    blodSize : 1024*1024*10, //文件分片大小
    method : 'POST', //请求方式
    fileObjName : 'file', //后台接收的文件名(后台使用spring mvc时此项不必要)
    uploadUrl : 'http://localhost:8080/file/uploadFile', //文件上传地址
    getUploadedSizeUrl : 'http://localhost:8080/file/uploadSize' ,//获取文件已上传大小地址
    getUploadFileInfoUrl:'http://localhost:8080/file/getUploadFileInfo',
    getRealFileNameUrl:'http://localhost:8080/file/getRealFileName',
    delTempFileUrl:'http://localhost:8080/file/delTempFile',
    hash:"",
};
/*监听文件是否改变*/
$(function () {
    $("#myupload").change(function (e) {
        opt.hash="";//重新计算哈希值
       var file = e.target.files[0];
       console.log(file.lastModifiedDate.getTime());
        fileObj.name = file.name;
        // $('#filename').val(file.name);
        $('#tempFileName').val(file.name);
        fileObj.size = file.size;//文件初始大小
        fileObj.oldFile = file;
        fileObj.upLoadSize = 0;

        afterChange(file);
        var flag = true;
        var newName="";
        var prefix = fileObj.name.substr(0,fileObj.name.lastIndexOf('.'));
        var suffix = fileObj.name.substr(fileObj.name.lastIndexOf('.'));
        var uploadFileInfo=null;
        var i = 1;
        while(flag){
            uploadFileInfo  = getUploadFileInfo(fileObj.oldFile);
            if(uploadFileInfo==''){
                flag = false;
            }else{

                $('#tempFileName').val(prefix+"-part"+ (i) +suffix);
                fileObj.name= prefix+"-part"+ i++ +suffix;
            }
        }
        var blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice,
            file = this.files[0],
            chunkSize = 1024*1024*100,                             // Read in chunks of 100MB
            chunks = Math.ceil(file.size / chunkSize),
            currentChunk = 0,
            spark = new SparkMD5.ArrayBuffer(),
            fileReader = new FileReader();

        var sparkmd5 = spark.end();
        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 {
                var arrN = utf8Str2ArrayBuffer(file.name,true);
                var arrU = utf8Str2ArrayBuffer(file.lastModifiedDate.getTime()+"",true);
                spark.append(arrN);
                spark.append(arrU);
                var localhash = spark.end();
                console.log('finished loading');
                console.log(localhash);
                $('#temphashcode').val(localhash);
                var realFilename;
                //获取哈希相同的文件名
                $.ajax({
                    url : opt.getRealFileNameUrl,
                    data : {'name':fileObj.name,"hash":localhash},
                    async:false,
                    type : 'POST',
                    success : function(returnData){
                        realFilename = returnData.fileName;
                        $('#fileName').val(returnData.tempFileName);
                    }
                });
                /*if(localhash==servhash){
                    deleteTempFile(file);
                    $('#tempFileName').val($('#filename'));
                    fileObj.upLoadSize=getUpLoadSize(file);
                }*/
                if(realFilename!=null && realFilename!=''){
                    $('#tempFileName').val(realFilename);
                    fileObj.upLoadSize=getUpLoadSize(file);
                }
            }
        };
        fileReader.onerror = function () {
            console.warn('oops, something went wrong.');
        };
        function loadNext() {
            var start = currentChunk * chunkSize,
                end = ((start + chunkSize) >= file.size) ? file.size : start + 1024*1024;
            fileReader.readAsArrayBuffer(blobSlice.call(file, start, end));
        }
        loadNext();
    });
    
    //监听选择文件按钮
    $("#upload").click(function (e) {
        $("#myupload").click()
    });
    
    //监听暂停按钮
    $("#isPauseButton").click(function (e) {
        var v1 = Number($("#isPause").val());
        if(v1==1){
            $("#isPause").val(0);
            $("#isPauseButton").text("继续")
        }else{
            $("#isPause").val(1);
            $("#isPauseButton").text("暂停")
            var blob = getBlod(fileObj.oldFile);
            sendBlob(opt.uploadUrl,blob,{'name':fileObj.name});
        }
    });
    
    //选择文件之后
    var afterChange = function(file){
       var str = '<div class="progress" style="width:400px;">'
            +'<div id="progress" class="progress-bar progress-bar-success progress-bar-striped" role="progressbar" '
            +'aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width:0%;">'
            +'</div></div>'
            +'  <span id="filename">'+fileObj.name+'</span>  <button class="btn btn-primary fileupload">上传</button>  ';
       $("#uploadProgress").html(str);
       
       $('.fileupload').on('click',(function(){
         return function(){upload(file);}
      })(file));

    }

    //点击上传按钮事件后响应函数
    var upload = function(file){


        console.log(fileObj.name);
        var blob = getBlod(fileObj.oldFile);
       sendBlob(opt.uploadUrl,blob,{'name':fileObj.name});
    }

    /**
     * 分割文件
     * @param file
     * @returns {string|Blob|Array.<T>|ArrayBuffer|*}
     */
    var getBlod = function (file) {
       var upLoadSize = 0;
       if(!fileObj.upLoadSize > 0){
          upLoadSize = getUpLoadSize(file);
       }else{
          upLoadSize = fileObj.upLoadSize;
       }
        var end = Number(upLoadSize)+Number(opt.blodSize);
        var BoldFile = file.slice(upLoadSize,end);

        return BoldFile;
    }

    /**
     * 获取已上传文件大小
     * @param file
     * @returns {number}
     */
    var getUpLoadSize = function (file) {

        var uploadedSize = 0;
        $.ajax({
            url : opt.getUploadedSizeUrl,
            data : {'name':fileObj.name,'size':fileObj.size,"fileSize":fileObj.size,"hash":$("#temphashcode").val()},
            async:false,
            type : 'POST',
            success : function(returnData){
                uploadedSize = returnData.size;
                $('#hashcode').val(returnData.hashcode);
            }
        });

        return uploadedSize;
    }

    var getUploadFileInfo = function (file) {
        var uploadFileInfo;
        $.ajax({
            url:opt.getUploadFileInfoUrl,
            data : {'name':fileObj.name},
            async:false,
            type : 'POST',
            success : function(returnData){
                uploadFileInfo = returnData;
            }
        });
        return uploadFileInfo;
    }

    /**
     * 上传文件块
     * @param url
     * @param file
     * @param formdata
     */
    var sendBlob = function(url,file,formdata){
        fileObj.name = $('#tempFileName').val();
        var v1 = Number($("#isPause").val());
        var xhr=new XMLHttpRequest();
        xhr.open(opt.method, url, true);
        xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
        var fd = new FormData();

        fd.append(opt.fileObjName,file);
        fd.append('fileNameT',fileObj.name);
        console.log(file);
        // fd.apend("fileTemp",file.name)
        if(formdata){
            for(key in formdata){
                fd.append(key,formdata[key]);
            }
        }
        xhr.send(fd);

        xhr.onreadystatechange = function(e) {
            if (xhr.readyState == 4) {
                fileObj.uploadOver = true;
                if (xhr.status == 200) {
                    //console.log("over")
                    fileObj.upLoadSize = getUpLoadSize(file);
                    onProgress(file, fileObj.upLoadSize, fileObj.size);
                    if(fileObj.upLoadSize < fileObj.size && v1==1){
                       //console.log(fileObj.upLoadSize)
                        sendBlob(opt.uploadUrl,getBlod(fileObj.oldFile),{'name':fileObj.name});
                    }else{
                        $.ajax({
                            url:opt.delTempFileUrl,
                            data : {'name':$('#fileName').val()},
                            type:'POST',
                            success : function(returnData){
                                console.log("成功删除副本文件")
                            }
                        });
                    }
                }
            }
        }
    }

    /**
     * 进度条处理
     * @param file
     * @param loaded
     * @param size
     */
    var onProgress = function (file, loaded, size) {
       console.log("本次已上传:"+loaded)
       console.log("upLoadSize:"+fileObj.upLoadSize)
       
       var p = (((parseInt(fileObj.upLoadSize))/parseInt(fileObj.size))*100).toFixed(2)
        console.log(p)
        $("#progress").css('width',p+'%');
       var percentText = p > 100 ? '100.00%' : p +'%';
       $("#bfb").html(percentText);
    }

    function utf8Str2ArrayBuffer(str, returnUInt8Array) {
        var length = str.length,
            buff = new ArrayBuffer(length),
            arr = new Uint8Array(buff),
            i;

        for (i = 0; i < length; i += 1) {
            arr[i] = str.charCodeAt(i);
        }

        return returnUInt8Array ? arr : buff;
    }

});

4、后台代码

 
 
package com.zhang.controller;

import com.zhang.pojo.UploadFileInfo;
import com.alibaba.fastjson.JSON;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.RandomAccessFile;
import java.util.Iterator;

@Controller
@RequestMapping("/file")
public class FileController {

    public static String PATH = "e:/testUpload";

    @RequestMapping("index")
    public String index(){
        return "file/demo";
    }

    @RequestMapping(value = "getRealFileName",method = RequestMethod.POST)
    @ResponseBody
    public UploadFileInfo getRealFileName(HttpServletRequest request){
        UploadFileInfo uploadFileInfo = new UploadFileInfo();

        String name = request.getParameter("name");
        uploadFileInfo.setFileName(name);
        String hash = request.getParameter("hash");
        String realFileName = name;
        if(name.contains("-part")){
            try {
                JedisShardInfo jedisShardInfo = new JedisShardInfo("10.18.10.101");
                Jedis jedis = new Jedis(jedisShardInfo);
                int len = new Integer(name.substring(name.lastIndexOf("-part")+5,name.lastIndexOf("."))).intValue();

                String oldFileName = name.substring(0,name.lastIndexOf("-part"))+name.substring(name.lastIndexOf("."));
                String str = jedis.get(oldFileName);
                if(StringUtils.isNotBlank(str)){
                    UploadFileInfo uploadFileInfot = JSON.parseObject(str,UploadFileInfo.class);
                    if(hash.equals(uploadFileInfot.getHashcode())){
                        uploadFileInfo = uploadFileInfot;
                        if(!uploadFileInfot.getFileName().equals(name)){
                            uploadFileInfo.setTempFileName(name);
                        }
                    }
               
                    for(int i=1;i<len-1;i++){
                        oldFileName = name.substring(0,name.lastIndexOf("-part"))+"-part"+i+name.substring(name.lastIndexOf("."));
                        str = jedis.get(oldFileName);
                        if (StringUtils.isNotBlank(str)){
                            uploadFileInfot = JSON.parseObject(str,UploadFileInfo.class);
                            if(hash.equals(uploadFileInfot.getHashcode())){
                                realFileName = uploadFileInfo.getFileName();
                                uploadFileInfo = uploadFileInfot;
                                if(!uploadFileInfot.getFileName().equals(name)){
                                    uploadFileInfo.setTempFileName(name);
                                }
                                break;
                            }
                        }
                    }
                }

                jedis.close();
            }catch (Exception e){
                e.printStackTrace();
            }
        }
        return uploadFileInfo;
    }

    @RequestMapping(value = "getUploadFileInfo", method = RequestMethod.POST)
    @ResponseBody
    public UploadFileInfo getUploadFileInfo(HttpServletRequest request){
        UploadFileInfo uploadFileInfo = null;
        String name = request.getParameter("name");
        try {
            JedisShardInfo jedisShardInfo = new JedisShardInfo("10.18.10.101");
            Jedis jedis = new Jedis(jedisShardInfo);
            String str = jedis.get(name);
            if(!StringUtils.isEmpty(str)){
                uploadFileInfo = JSON.parseObject(str,UploadFileInfo.class);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return uploadFileInfo;
    }

    @RequestMapping(value = "/uploadSize",method = RequestMethod.POST)
    @ResponseBody
    public UploadFileInfo uploadSize(HttpServletRequest request){

        String name = request.getParameter("name");
        Long size = Long.parseLong(request.getParameter("size"));
        String hash=request.getParameter("hash");
        try {
            JedisShardInfo jedisShardInfo = new JedisShardInfo("10.18.10.101");
            Jedis jedis = new Jedis(jedisShardInfo);
            String str = jedis.get(name);
            UploadFileInfo uploadFileInfo = null;
            //如果首次上传
            if(StringUtils.isEmpty(str)){
                uploadFileInfo = new UploadFileInfo();
                uploadFileInfo.setHashcode(hash);
                jedis.set(name, JSON.toJSONString(uploadFileInfo));
                jedis.close();
                return uploadFileInfo;
            }
            uploadFileInfo = JSON.parseObject(str,UploadFileInfo.class);
            if(StringUtils.isEmpty(uploadFileInfo.getHashcode())){
                uploadFileInfo.setHashcode(hash);
                jedis.set(name,JSON.toJSONString(uploadFileInfo));
            }
            System.out.println(uploadFileInfo.getFileName()+":"+uploadFileInfo.getSize()+":"+uploadFileInfo.getHashcode());
            jedis.close();
            //全部上传成功
            if (uploadFileInfo.getSize()!=null&&size <= uploadFileInfo.getSize()){
                System.out.println("上传完成");
            }
            return uploadFileInfo;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    @RequestMapping(value = "/uploadFile",method = RequestMethod.POST)
    @ResponseBody
    public int upload(HttpServletRequest request, @RequestParam(value = "file",required = false) MultipartFile multipartFile){
        MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
        Iterator<String> t = multiRequest.getFileNames();
        MultipartFile fileDetail = multiRequest.getFile(t.next());
        String name = request.getParameter("name");
        JedisShardInfo jedisShardInfo = new JedisShardInfo("10.18.10.101");;
        Jedis jedis  = new Jedis(jedisShardInfo);
        String uploadF = jedis.get(name);
        if(StringUtils.isNotBlank(uploadF)){
            UploadFileInfo uploadFileInfo = JSON.parseObject(uploadF,UploadFileInfo.class);
            uploadFileInfo.setFileName(name);
            String hashcode = uploadFileInfo.getHashcode();
            File file = new File(PATH);
            if(!file.exists() && !file.isDirectory()){
                boolean f = file.mkdir();
            }
            File testF = new File(PATH+"/"+name);
            RandomAccessFile randomFile = null;
            try {
                randomFile = new RandomAccessFile(PATH+"/"+name,"rw");
                randomFile.seek(randomFile.length());;
                randomFile.write(fileDetail.getBytes());
                uploadFileInfo.setLocalPath(PATH+"/"+name);
                uploadFileInfo.setSize(randomFile.length());
                randomFile.close();
            } catch (Exception e) {
                e.printStackTrace();
            }
            //将上传信息保存到redis
            jedis.set(name,JSON.toJSONString(uploadFileInfo));
        }
        jedis.close();
        return 0;
    }

    @RequestMapping(value = "delTempFile",method = RequestMethod.POST)
    @ResponseBody
    public int delTempFile(HttpServletRequest request){
        String name = request.getParameter("name");
        if(StringUtils.isNotBlank(name)){
            JedisShardInfo jedisShardInfo = new JedisShardInfo("10.18.10.101");;
            Jedis jedis  = new Jedis(jedisShardInfo);
            jedis.del(name);
            jedis.close();
            File file = new File(PATH+"/"+name);
            if (file.exists()&&!file.isDirectory()){
                file.delete();
            }
        }
        return 0;
    }
}

5、pojo对象类:

 
 
public class UploadFileInfo {

    private String tempFileName;

    private long id;

    private String hashcode;

    private String fileName;

    public String getFileName() {
        return fileName;
    }

    private String localPath;

    private String fileSize;

    private Long size;




猜你喜欢

转载自blog.csdn.net/zeratyl/article/details/78415520