java大文件分块上传分享

    先说说大文件上传种用的点以及原理,也希望各位指正。

    思路以及大部分源码来自于  haohao123naa博主,我只是在他的基础上进行完善点击打开链接,在此表示感谢。

    1.文件分块:一个超过几个G的文件上传到服务器,如果你只使用最简单上传、接收、处理、还能成功的话,我只能说你家服务器真好。就算服务器够好,这种操作也时不被允许的。所以我们要想办法解决这种困难。

    首先我们要解决大文件的问题,没有办法只能切成几M的 byte小文件多次发送至服务器,并保存下来。然后给这些文件用源文件的MD5+index进行命名,当然也有朋友用UUID+index进行命名,这两种的区别会在下文详细讲述。当你把这些小文件分别上传到服务器上时,最好把这些记录保存到数据库。

         (1)当第一个分块上传完成时,将源文件的名称、类型、源文件的MD5、上传日期、地址、未完成的状态写入到一张表,等拼接完成改状态为完成。暂时命名为file表

         (2)每一个分块上传完成后记录保存到数据库里面,源文件的MD5+index名字分块的MD5(这是一个重点)上传时间、文件地址。保存进数据库 命名为file__tem表

    2.秒传功能:很多网盘都实现了这个功能,上传开始时发送Ajax请求,查询本次要上传的文件,是否存在,这里我们H5提供了获取文件MD5的方法,然后用ajax去file里请求这个md5是否存在、状态是否时完成,存在的情况下,也要验证本地这个文件是不是还存在这。同时存在的情况下。就可以给前台返回存在状态了,然后你就可以傲娇的告诉客户,秒传了。

    3.断点续传:这里就为什么我们为什么不用简单的UUID进行命名,而是使用MD5的原因了,大文件上传失败是很常见的一种情况,现在分成一块块的小文件了,失败了我们就从失败的那个小文件开始继续上传不就可以了。

    (1)Ajax 请求file 表、存在记录、状态未完成。(状态完成就是秒传了)

    (2)文件分块 Ajax用MD5请求file_temp表是否存在,存在递归下一块的MD5请求,

    (3)第二步不存在的情况下、这里再用form提交MultipartFile以及相关信息,上传成功后,写入数据库。

    4.所有分块完成拼接到一起,改file表状态。

    5.源码部分(本人代码写的不是很好,希望各位指正)

       (HTML)

<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title></title>
 <meta name="renderer" content="webkit">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
<link rel="stylesheet" href="./plugins/layui/css/layui.css" media="all">
<style>
.form-wrap {
	padding: 10px;
}
</style>
</head>
<body>
	<!-- 新增用户表单 -->
	<form id="videofile_form" class="layui-form" style="display: none"
		method="post" enctype="multipart/form-data">
		<div class="layui-form-item" style="display: none">
			<label class="layui-form-label">文件上传</label>
			<!--  name="expertfile" -->
			<div class="layui-input-block">
				<input type="text" id="parentId" name="parentId" >
				<input type="text" id="videoId" name="videoId" >
				<input type="text" id="videoSize" name="videoSize" > <!-- //大小 -->
				<input type="text" id="timeLength" name="timeLength" >   <!-- //时长 -->
				<input type="text" id="videoPath" name="videoPath" >   <!-- //路径-->
			    <input type="text" id="type" name="type" >   <!-- //类型 -->
			</div>
		</div>
		<div class="layui-form-item">
			<label class="layui-form-label">视频上传</label>
			<input type="file" id="file" />
		</div>
		<div class="layui-form-item">
			<label class="layui-form-label">视频名称</label>
			<div class="layui-input-block">
				<input type="text" name="videoName" lay-verify="title" placeholder="请输入" class="layui-input">
			</div>
		</div>
		<div class="layui-form-item">
			<label class="layui-form-label">教师名称</label>
			<div class="layui-input-block">
				<input type="text" name="teacherName" lay-verify="title"
					placeholder="请输入" class="layui-input">
			</div>
		</div>
		<div class="layui-form-item">
			<label class="layui-form-label">图书简介</label>
			<div class="layui-input-block">
				<textarea name="introduction" id="introduction_textarea"></textarea>
			</div>
		</div> 
		<div class="layui-form-item" style="display: none">
			<div class="layui-input-block">
				<button type=" " class="layui-btn layui-btn-primary"
					id="deleteclean">重置</button>
			</div>
		</div>
	</form>
	<div class="layui-progress layui-progress-big" lay-showpercent="true"
		lay-filter="demo" id="progress" style="display: none">
		<div class="layui-progress-bar layui-bg-red" lay-percent="0%"></div>
	</div>
	<div class="layui-form-item" id="expert_submit" style="display: block">
		<div class="layui-input-block">
			<div class="site-demo-button"
				style="margin-top: 20px; margin-bottom: 0;">
				<!-- data-type="loading"  -->
				
			<!-- 	 <button id="upload">上传</button> -->
				<button class="layui-btn site-demo-active"  οnclick="window.active.loading();">提交</button>
				<button type=" " class="layui-btn layui-btn-primary" id="cleanbu"
					οnclick="clean.deleteclean();">重置</button>
			</div>
		</div>
	</div>
	<script src="./plugins/layui/layui.js"></script>
	<script src="../publicjs/jquery-1.8.0.min.js"></script>
	<script src="../publicjs/hxwmutil.js"></script>
    <script src="../publicjs/md5.js"></script>
	<script type="text/javascript">
    var i = -1;
    var succeed = 0;
    var databgein;  //开始时间
    var dataend;    //结束时间
    var paid;
    var id ;
    var Percent=0;
    var action=false;    //false检验分片是否上传过(默认); true上传文件       	
	$(function() {
		var moudle = commonUtil.getRequestParam("moudle");
		$('#videofile_form').show();
		// 展示当前的表单
		switch (moudle) {
		case "expert":
			formObj.expertForm.operType = "insert";
		}
	});
		layui.use([  'form','upload','tree', 'layer', 'element', 'table','layedit' ],function() {
			var form = layui.form, 
			layer = layui.layer,
			table = layui.table, 
			layedit = layui.layedit, 
			element = layui.element;
			var $ = layui.jquery,upload = layui.upload;
	     id = commonUtil.getRequestParam("id");   //节点Id
		 paid = commonUtil.getRequestParam("paid"); //课程ID
		$("#parentId").val(id)
			var introductionEditor = layedit.build('introduction_textarea');
		   //触发事件
		 		window.active = {
				setPercent: function(){
				//设置50%进度
			      element.progress('demo', '0%')
				}, 
				loading : function() {
					    var othis = $(this), type = $(this).data('type');
					    active[type] ? active[type].call(this,othis) : '';
						$("#progress").attr('style','disply:block');
						var DISABLED = 'layui-btn-disabled';
						if (othis.hasClass(DISABLED))
							return; 
		             databgein=new Date();
		             var file = $("#file")[0].files[0];  //文件对象
		             isUpload(file);
					 //模拟loading
					 active.setPercent();
					 var n = 0, timer = setInterval(function() {
					 // 请求ajax成功之后 将课程列表放到课程下拉框里
					 if (Percent>=100 ) {
						Percent= 100;
						clearInterval(timer);
						othis.removeClass(DISABLED);
					 }
					 element.progress('demo',Percent+"%");
					 // n = n + Math.random()*10|0;
					 }, 300 + Math.random() * 1000);
						othis.addClass(DISABLED); 
				   } 
			   } 
		}); 
		var clean = {
			deleteclean : function() {
				$("#deleteclean").click()
			}
		}
		 function isUpload (file) {
            //构造一个表单,FormData是HTML5新增的
            var form = new FormData();
           var r = new FileReader();
           r.readAsBinaryString(file);
            $(r).load(function(e){
            var bolb = e.target.result;
           var strmd5 = hex_md5(bolb);
            form.append("filemd5", strmd5);  
            //Ajax提交
            $.ajax({
                url: "bigfile/isUpload",
                type: "POST",
                data: form,
                async: true,        //异步
                processData: false,  //很重要,告诉jquery不要对form进行处理
                contentType: false,  //很重要,指定为false才能形成正确的Content-Type
                success: function(data){
                var uuid = data.fileId;
                if (data.flag == "1") {
                //没有上传过文件
                 var a = upload(file,uuid,strmd5,data.date);
                } else if(data.flag == "2") {
                //已经上传部分
                upload(file,uuid,strmd5,data.date);
                                          }else if(data.flag == "3") {
                    //文件已经上传过
                    Percent=99;
			          update(data);
                                          }
                },error: function(XMLHttpRequest, textStatus, errorThrown) {
                  alert("服务器出错!");
                }
              })
            })
            };
		/*
		 * file 文件对象
		 * uuid 后端生成的uuid
		 * filemd5 整个文件的md5
		 * date  文件第一个分片上传的日期(如:20170122)
		*/
		function upload (file,uuid,filemd5,date) {
		name = file.name;        //文件名
		size = file.size;        //总大小
		var shardSize = 512 * 1024,    //以1MB为一个分片
		shardCount = Math.ceil(size / shardSize);  //总片数
		    if (i > shardCount) {
		        i = -1;
		        i = shardCount;
		    } else {
		        if(!action){
		        i += 1;  //只有在检测分片时,i才去加1; 上传文件时无需加1
		        }
		    }
            //计算每一片的起始与结束位置
            var start = i * shardSize,
            end = Math.min(size, start + shardSize);
            //构造一个表单,FormData是HTML5新增的
            var form = new FormData();
            if(!action){
            form.append("action", "check");  //检测分片是否上传
            $("#param").append("action==check ");
            }else{
            form.append("action", "upload");  //直接上传分片
            form.append("data", file.slice(start,end));  //slice方法用于切出文件的一部分
            $("#param").append("action==upload ");
            }
            form.append("uuid", uuid);
            form.append("filemd5", filemd5);
            form.append("date", date);
            form.append("name", name);
            form.append("size", size);
            form.append("total", shardCount);  //总片数
            form.append("index", i+1);        //当前是第几片
            var ssindex = i+1;
            //按大小切割文件段  
            var data = file.slice(start, end);
                   var r = new FileReader();
                      r.readAsBinaryString(data);
            $(r).load(function(e){
            var bolb = e.target.result;
            var md5 = hex_md5(bolb);
            form.append("md5", md5);  
            //var formData = new FormData(form);
            //Ajax提交
            $.ajax({
            url: "bigfile/upload",
            type: "POST",
            data: form,
            async: false,        //异步
            processData: false,  //很重要,告诉jquery不要对form进行处理
            contentType: false,  //很重要,指定为false才能形成正确的Content-Type
            success: function(data){
            var fileuuid = data.fileId;
            var flag = data.flag;
            //服务器返回该分片是否上传过
            if(!action){
            if (flag == "1") {
            //未上传
            action = true;
            } else if(flag == "3") {
            //已上传
            action = false;
            ++succeed;                
            } 
            upload(file,uuid,filemd5,date);
            //递归调用                        
            }else{
          	 if(flag == "4") {
                  alert("上传失败,请检查网络");        
                  return false;
   		     }else if(flag == "5") {
   		    	$('#videoPath').val(data.path);
   				$('#timeLength').val(data.timelength);
   				$('#videoSize').val(data.size);
   			    $('#type').val(data.type);
       		    update(data);
       			}      
            //服务器返回分片是否上传成功
            //改变界面
            ++succeed;
            $("#output").text(succeed + " / " + shardCount);
            var a = GetPercent(succeed,shardCount);
            if(!a){
            	 alert("抱歉,请上传正确视频");
            	return false;
            }
            if (i+1 == shardCount) {
            dataend=new Date();
            } else {                        
              //已上传成功,然后检测下一个分片
              action=  false;
            //递归调用                 
            upload(file,uuid,filemd5,date);
           }   
           }
	       },error: function(XMLHttpRequest, textStatus, errorThrown) {
	          alert("抱歉,请重试");
	         }
         });
        })               
   }
		function update(data){
			   var parap = {
    				videoCourseId : paid
    			}
       			var userForm = document.getElementById("videofile_form");
                		var formData = new FormData(userForm);
                		var url ="";
                		if($("#parentId").val()!=""){
                			url = "video/update";
                		}else{
                			layer.alert("请选择节点");
                			return;
                		}
                		var ajaxParam = { 
                		url : url,
                		async : false
                		}
         		ajaxUtil.submitForm(formData,ajaxParam,function(data) {
         			if (data.code = 200) {
         			// 关闭当前的表单弹窗 刷新父级页面的数据表格
         			var parentHtml = window.parent;
         			parentHtml.layer.closeAll();
         			parentHtml.refresh(parap);
        		    }else if(res.code=='400'){
        			   layer.alert(res.msg);
        			}
         		  }) 
		    }	
		function GetPercent(num, total) { 
			num = parseFloat(num); 
			total = parseFloat(total); 
			if (isNaN(num) || isNaN(total)) { 
			return false; 
			} 
		    Percent = (Math.round(num / total * 10000) / 100.00); 
		    return true;
			} 
</script>
</body>
</html>

   ( controller部分)

package com.folkestone.hxwm.controller.base;


import com.folkestone.hxwm.service.commom.ResService;
import com.folkestone.hxwm.service.commom.FileResService;
import com.folkestone.hxwm.bean.bean_dto.common.FileRes;
import com.folkestone.hxwm.common.util.bigfileup.DataUntil;
import com.folkestone.hxwm.common.util.bigfileup.FileMd5Util;
import com.folkestone.hxwm.common.util.bigfileup.FileOpera;
import com.folkestone.hxwm.common.util.bigfileup.NameUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.*;
/**
 * Created by Administrator on 2015/10/9.
 */
@RestController
@RequestMapping(value ="/admin/bigfile")
public class BFileUController {
    @Autowired
    private FileResService fileResService;
    @Autowired
    private ResService resService;




    /**
     * 上传文件
     *
     * @param request
     * @return
     * @throws IllegalStateException
     * @throws IOException
     */
    @RequestMapping(value = "/upload")
    public Map<String, Object> upload(
            HttpServletRequest request, @RequestParam(value = "data",required = false)
            MultipartFile multipartFile) throws IllegalStateException, IOException, Exception {
        String action = request.getParameter("action");
        String uuid = request.getParameter("uuid");
        String fileName = request.getParameter("name");
        int size =  Integer.valueOf(request.getParameter("size"));//总大小
        int total = Integer.valueOf(request.getParameter("total"));//总片数
        int index = Integer.valueOf(request.getParameter("index"));//当前是第几片
        String fileMd5 = request.getParameter("filemd5"); //整个文件的md5
        String date = request.getParameter("date"); //文件第一个分片上传的日期(如:20170122)
        String md5 = request.getParameter("md5"); //分片的md5
    	//文件夹路径
    	String saveDirectory= FileOpera.CreatePath(date,uuid);
        //分片文件
    	File path = new File(saveDirectory);
	    if (!path.exists()) {
	         path.mkdirs();
	    }
        File file = new File(saveDirectory, uuid + "_" + index);
        //根据action不同执行不同操作. check:校验分片是否上传过; upload:直接上传分片
        Map<String, Object> map = null;
        if("check".equals(action)){
            String md5Str = FileMd5Util.getFileMD5(file);
            //已经上传部分文件 断点续传
            if (md5Str != null && md5Str.length() == 31) {
            //查询临时表 当前片段MD5是否存在
            List<FileRes> li= resService.select(md5,file.getPath());
            //查看当前片段是否上传
            map = new HashMap<>();
            map=FileOpera.FileExit(li);  
            //返回执行下一段
            return map;
            }else {
            	 //重新上传一次
           	    map = new HashMap<>();
                map.put("flag", "1");
                map.put("fileId", uuid);
                map.put("status", true);
                return map;
            }
        }else if("upload".equals(action)){
             map = new HashMap<>();
             int a = -1;
            //未上传
            //删除文件后上传	 
     	   if (file.exists()) {
                file.delete();
            }
     	  multipartFile.transferTo(new File(saveDirectory, uuid + "_" + index));
     	   //添加进数据库
            FileRes fileRes = new FileRes();
            fileRes.setUuid(uuid);
            fileRes.setPath(file.getPath());
            fileRes.setSize(size);
            fileRes.setMd5(md5);
            fileRes.setStatus(1);
            fileRes.setCreateTime(DataUntil.Tidata());
            a=resService.insert(fileRes);
            if(a<0) {//片段失败重新上传
            	 map = new HashMap<>();
                 map.put("flag", "4");
                 map.put("fileId", uuid);
                 map.put("status", false);
                 return map;
            }
        }
        if (path.isDirectory()) {
            File[] fileArray = path.listFiles();
            if (fileArray != null) {
                if (fileArray.length == total) {
                	int success=-1;
                    //分块全部上传完毕,合并
                    String suffix = NameUtil.getExtensionName(fileName);
                    File newFile = new File(FileOpera.Createfolder(date), uuid + "." + suffix);
                    FileOutputStream outputStream = new FileOutputStream(newFile, true);//文件追加写入
                    byte[] byt = new byte[10 * 1024 * 1024];
                    int len;
                    FileInputStream temp = null;//分片文件
                    for (int i = 0; i < total; i++) {
                        int j = i + 1;
                        temp = new FileInputStream(new File(saveDirectory, uuid + "_" + j));
                        while ((len = temp.read(byt)) != -1) {
                            outputStream.write(byt, 0, len);
                        }
                    }
                    //关闭流
                    temp.close();
                    outputStream.close();
                    //修改FileRes记录为上传成功
                    FileRes fileRes = new FileRes();
                    fileRes.setStatus(1);
                    fileRes.setMd5(fileMd5);
                    fileRes.setPath(newFile.getPath());
                    fileRes.setSize((int) newFile.length());
                    fileRes.setSuffix(NameUtil.getExtensionName(fileName));
                    success =fileResService.update(fileRes);
                    map=new HashMap<>();
                    map.put("fileId", uuid);
                    map.put("flag", "5");
                    if(success>0) {
		        	map.put("size",fileRes.getSize());
		            map.put("timelength",fileRes.getTimeLength());
		            map.put("type",fileRes.getSuffix());
		        	map.put("status", true);
		        	map.put("path",fileRes.getPath());
                    }else {
                    	 map.put("status", false);
                    }
                    return map;
                }else if(index == 1){
                    //文件第一个分片上传时记录到数据库
                    FileRes fileRes = new FileRes();
                    fileRes.setMd5(fileMd5);
                    List<FileRes> list = fileResService.selectByMd(fileRes);
                    String name = NameUtil.getFileNameNoEx(fileName);
                    if (name.length() > 50) {
                        name = name.substring(0, 50);
                    }
                    fileRes.setName(name);
                    fileRes.setSuffix(NameUtil.getExtensionName(fileName));
                    fileRes.setUuid(uuid);
                    fileRes.setPath(FileOpera.Createfolder(date) + File.separator + uuid + "." + fileRes.getSuffix());
                    fileRes.setSize(size);
                    fileRes.setStatus(0);
                    fileRes.setCreateTime(DataUntil.Tidata());
                    if (list == null || list.size() == 0) {
                    this.fileResService.insert(fileRes);
                      }else {
                    this.fileResService.update(fileRes);	  
                      }
                }
            }
        }
        map = new HashMap<>();
        map.put("flag", "3");
        map.put("fileId", uuid);
        map.put("status", true);
        return map;
    }


    /**
     * 上传文件前校验
     *
     * @param request
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/isUpload")
    public Map<String, Object> isUpload(HttpServletRequest request,MultipartFile multipartFile) throws Exception {
    	String md5 = request.getParameter("md5");
        //查看本文件是否存在
    	FileRes fi = new FileRes();
    	fi.setMd5(md5);
    	fi.setStatus(1);
        List<FileRes> list = fileResService.selectByMd(fi);
        return FileOpera.FileExit(list);
    }
}
工具类部分:
package com.folkestone.hxwm.common.util.bigfileup;

import java.io.File;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.MessageDigest;

/**
 * @author cuihao
 * @create 2017-01-20-15:13
 */

public class FileMd5Util {
    public static final String KEY_MD5 = "MD5";
    public static final String CHARSET_ISO88591 = "ISO-8859-1";
    /**
     * Get MD5 of one file:hex string,test OK!
     *
     * @param file
     * @return
     */
    public static String getFileMD5(File file) {
        if (!file.exists() || !file.isFile()) {
            return null;
        }
        MessageDigest digest = null;
        FileInputStream in = null;
        byte buffer[] = new byte[1024];
        int len;
        try {
            digest = MessageDigest.getInstance("MD5");
            in = new FileInputStream(file);
            while ((len = in.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }
            in.close();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        BigInteger bigInt = new BigInteger(1, digest.digest());
        return bigInt.toString(16);
    }

    /***
     * Get MD5 of one file!test ok!
     *
     * @param filepath
     * @return
     */
    public static String getFileMD5(String filepath) {
        File file = new File(filepath);
        return getFileMD5(file);
    }

    /**
     * MD5 encrypt,test ok
     *
     * @param data
     * @return byte[]
     * @throws Exception
     */
    public static byte[] encryptMD5(byte[] data) throws Exception {

        MessageDigest md5 = MessageDigest.getInstance(KEY_MD5);
        md5.update(data);
        return md5.digest();
    }

    public static byte[] encryptMD5(String data) throws Exception {
        return encryptMD5(data.getBytes(CHARSET_ISO88591));
    }
    /***
     * compare two file by Md5
     *
     * @param file1
     * @param file2
     * @return
     */
    public static boolean isSameMd5(File file1,File file2){
        String md5_1= FileMd5Util.getFileMD5(file1);
        String md5_2= FileMd5Util.getFileMD5(file2);
        return md5_1.equals(md5_2);
    }
    /***
     * compare two file by Md5
     *
     * @param filepath1
     * @param filepath2
     * @return
     */
    public static boolean isSameMd5(String filepath1,String filepath2){
        File file1=new File(filepath1);
        File file2=new File(filepath2);
        return isSameMd5(file1, file2);
    }

}

package com.folkestone.hxwm.common.util.bigfileup;

import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import org.springframework.web.multipart.MultipartFile;

import com.folkestone.hxwm.bean.bean_dto.common.FileRes;
import com.folkestone.hxwm.common.util.ContantFinalUtil;

public class FileOpera {

	/** 
	 * 根据MD5查看文件是否已经上传
	 * 文件片段或者文件均可
	 *  
	 * */
	public static Map<String, Object> FileExit(List<FileRes> li) {
		 Map<String, Object> map = null;
		if (li == null || li.size() == 0) {
            //没有上传过文件
            String uuid = UUID.randomUUID().toString();
            map = new HashMap<>();
            map.put("flag", "1");
            map.put("fileId", uuid);
            map.put("date", DataUntil.StrDta());
            map.put("status", true);
        } else {
            FileRes fileRes = li.get(0);
            //判断文件是否删除  本地文件是否存在
            File file=new File(fileRes.getPath());    
        if(file.exists()) { 
            if(fileRes.getStatus()==0){
                //文件上传部分
                map = new HashMap<>();
                map.put("flag", "2");
                map.put("fileId", fileRes.getUuid());
                map.put("date",DataUntil.StrDta());
                map.put("status", true);
            }else if(fileRes.getStatus()==1){
                //文件上传成功
                map = new HashMap<>();
                map.put("flag", "3");
                map.put("path", fileRes.getPath());
                map.put("fileId", fileRes.getUuid());
                map.put("date",DataUntil.StrDta());
                map.put("status", true);
                map.put("size",fileRes.getSize());
                map.put("timelength",fileRes.getTimeLength());
                map.put("type",fileRes.getSuffix());
            }
            
          }else {
        	  //重新上传
        	  //删除表
        	  String uuid = UUID.randomUUID().toString();
              map = new HashMap<>();
              map.put("flag", "1");
              map.put("fileId", uuid);
              map.put("date", DataUntil.StrDta());
              map.put("status", true);
          }
        }
		return map;
	}
	/** 
	 * 创建文件路径
	 * @param string 
	 * @param date 
	 *  
	 * */
	public static String CreatePath(String date, String uuid) {
		  //生成上传文件的路径信息,按天生成
        String saveDirectory = ContantFinalUtil.BASE_PATH+ 
        	   ContantFinalUtil.VIDEO_PATH + File.separator + date + File.separator + uuid;
        //验证路径是否存在,不存在则创建目录
        File path = new File(saveDirectory);
        if (!path.exists()) {
            path.mkdirs();
        } 
		return saveDirectory;
	}
	/** 
	 * 创建文件夹路径
	 * @param string 
	 * @param date 
	 *  
	 * */
	public static String Createfolder(String date) {
		  //生成上传文件的路径信息,按天生成
        String saveDirectory = ContantFinalUtil.BASE_PATH+ 
        	   ContantFinalUtil.VIDEO_PATH + File.separator + date;
        //验证路径是否存在,不存在则创建目录
        File path = new File(saveDirectory);
        if (!path.exists()) {
            path.mkdirs();
        } 
		return saveDirectory;
	}
	public static Map<String, Object> upload(MultipartFile multipartFile, String saveDirectory, String Pname) {
		 Map<String, Object> map = null;
		 try {
			multipartFile.transferTo(new File(saveDirectory,Pname));
		} catch (IllegalStateException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		//写入 比较与前台传过来的MD5是否一致
		 
		 return map;
	}

     公司前端框架是layui,所以改成了这个样子,大家使用的时候自己修改吧。

下面说说这里的几个要点以及与完善原博主的地方:

(前端部分)

      1、md5.js  ,你只需要下载一个 MD5.js即可,(md5.js和jQuery.md5.js是部分相同的两种东西,我当时以为功能会相同,然后前台报错了,特此记录一下)

      2、添加了一个进度条,直接用 当前成功分块/总分块,求出的parcent,layui每500ms轮询一次请求这个值,自动生成的进度条。一个G,5M一块, 一共241块,所以这个进度条看着也可以,不知道大家有没有更好的进度条方式哪?请指点。谢谢。

(后端部分)

      1、我这里添加了数据操作,原博主是个大神不屑这些小地方。我补全了,留个记录方便自己。

      2、添加了断点续传的功能,理由同上。

      3、抽取了一个FileOpera为了断点上传的方便。

      4、在数据库种找到记录之后,有添加了一下验证本地。因为我们这边总会有不严谨的删除,很神奇。

最后说说需要改进的地方,以后有时间进行改进:

     1、后台接受form提交,我直接使用的 getParamerter,应该使用bean自动的。

     2、添加一个线程,可以一边上传,一边自动拼接,最后一次分块上传就会快很多。

     3、加一个分块文件七天删除的功能,每上传一次文件,服务器就会存了两份文件。你要是想用断点续传,就不能立刻删除这些分块文件。但是时间长了,就会对服务器造成压力。所以应该定时删除。


    第一次写博客,希望大家支持一下,哪里不足的也希望各位指点一下。谢谢。







        

 

评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值