springmvc分片上传,并合并。

思路:前台上传文件分片到后台存储,并保存路径为数组,上传完毕后合并,使用ajax同步上传,后期再优化
后台代码:
package com.savethink.web.opera.controller.video;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.channels.FileChannel;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.http.HttpServletRequest;
import org.springframework.beans.factory.annotation.Value;
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 com.savethink.web.opera.common.ControllerResult;
import com.savethink.web.opera.common.StringUtil;

/**
 * 视频上传
 * 
 * @author SaveThink
 *
 */
@Controller
@RequestMapping(value = "/videoUploadController")
public class VideoUploadController {

    @Value("${upload.file.root}")
    private String uploadRoot;

    @Value("${upload.file.video}")
    private String uploadVideo;

    @Value("${upload.file.video.type}")
    private String uploadVideoType;

    // 分片上传
    @RequestMapping(value = "/upload", method = RequestMethod.POST)
    @ResponseBody
    public ControllerResult upload(HttpServletRequest request) {
        ControllerResult result = new ControllerResult();
        
        MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
        // 获得文件:
        MultipartFile file = multipartRequest.getFile("file");
        int index = Integer.parseInt(multipartRequest.getParameter("index"));
        
        File uploadFile = new File(getUploadVideoPath() + File.separator + "temp", index+".tmp");
        if (!uploadFile.getParentFile().exists()) { // 判断文件父目录是否存在
            uploadFile.getParentFile().mkdirs();
        }
        createFile(file, uploadFile);
        
        File originalFilePath = new File(uploadFile.getParentFile().getPath().toString() + File.separator + file.getOriginalFilename());
        
        result.msg = uploadFile.toPath().toString();
        result.message = originalFilePath.toPath().toString();
        return result;
    }
    
    // 合并所有文件
    @RequestMapping(value = "/merge", method = RequestMethod.POST)
    @ResponseBody
    public ControllerResult merge(@RequestParam(value = "tempsFile[]") String[] tempsFile, HttpServletRequest request) {
        ControllerResult result = new ControllerResult();
        
        String originalFilePath = request.getParameter("originalFilePath");
        boolean flag = mergeFiles(tempsFile, originalFilePath);
        return result;
    }

    // 获取视频上传的路径
    private String getUploadVideoPath() {
        StringBuffer sb = new StringBuffer(uploadRoot);
        sb.append(File.separator);
        sb.append(uploadVideo);
        return sb.toString();
    }
    
    // 转储文件
    public static boolean createFile(MultipartFile file,File uploadFile) {
        boolean flag = false;
        try {
            file.transferTo(uploadFile);
            flag = true;
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return flag;
    }
    
    
    public static List<File> handleTempsPath(String filePath) {
        File file = new File(filePath);
        File[] fs = file.listFiles();
        List<File> files = new ArrayList<>();
        for(int i = 0; i < fs.length; i++) {
            if(fs[i].isFile()) {
                files.add(fs[i]);
                System.out.println(fs[i].getName());
            }
        }
        return files;
    }
    
    // 利用nio FileChannel合并多个文件
    @SuppressWarnings("resource")
    public static boolean mergeFiles(String[] fpaths, String resultPath) {
        if (fpaths == null || fpaths.length < 1 || StringUtil.isEmpty(resultPath)) {
            return false;
        }
        if (fpaths.length == 1) {
            return new File(fpaths[0]).renameTo(new File(resultPath));
        }

        File[] files = new File[fpaths.length];
        for (int i = 0; i < fpaths.length; i ++) {
            files[i] = new File(fpaths[i]);
            if (StringUtil.isEmpty(fpaths[i]) || !files[i].exists() || !files[i].isFile()) {
                return false;
            }
        }
        File resultFile = new File(resultPath);
        try {
            FileChannel resultFileChannel = new FileOutputStream(resultFile, true).getChannel();
            for (int i = 0; i < fpaths.length; i ++) {
                FileChannel blk = new FileInputStream(files[i]).getChannel();
                resultFileChannel.transferFrom(blk, resultFileChannel.size(), blk.size());
                blk.close();
            }
            resultFileChannel.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }

        for (int i = 0; i < fpaths.length; i ++) {
            files[i].delete();
        }

        return true;
    }

}
前台html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>文件上传</title>
<style>
#test {
    width: 200px;
    height: 100px;
    border: 1px solid green;
    display: none;
}

#img {
    width: 50px;
    height: 50px;
    display: none;
}

#upimg {
    text-align: center;
    font: 8px/10px '微软雅黑', '黑体', sans-serif;
    width: 300px;
    height: 10px;
    border: 1px solid green;
}

#load {
    width: 0%;
    height: 100%;
    background: green;
    text-align: center;
}
</style>
</head>
<body>
<form enctype="multipart/form-data">
    <div id="upimg">
        <div id="load"></div>
    </div>
    <input type="file" name="file" id="videoFile" />
    <input type="button" value="上传" onclick="upload();" />
    <input type="submit" value="submit" />
</form>
<div id="test">测试是否DIV消失</div>
<script type="text/javascript" src="lib/jquery/1.9.1/jquery.min.js"></script> 
<script type="text/javascript">
var token = parent.window.document.getElementById("token").value;

 // 发送请求
function upload(){
    // 进度条
    var progressBar=document.getElementById('load');
    var num=document.getElementById('upimg');
    
    var tempsFile=new Array();
    var blob = document.getElementById("videoFile").files[0];
    // 每片文件5M
    var perPiece = 1024 * 1024 * 50;
    var originalFilePath;
    var start = 0,
        end = 0,
        index = 0,
        totalPieces,
        filesize = blob.size,
        filename = blob.name;
    
    // 计算文件切片总数
    // totalPieces = Math.ceil(filesize / perPiece);
    totalPieces = filesize%perPiece==0?filesize/perPiece:filesize/perPiece+1;
    console.log("===================");
    console.log("切片总数:"+totalPieces);
    console.log("索引:"+index);
    // 如果文件为空,则退出
    if(!blob){
           alert('请选择文件');
           return;
      }
    
    // 上传文件
    while(start < filesize) {
        // 切片上传
        end = start + perPiece;
        if(end > filesize) {
            // 一次性上传
            end = filesize;
        }
        // 分割文件核心部分slice
        var chunk = blob.slice(start, end);
        var sliceIndex = blob.name + index;
        console.log("=========sliceIndex==========:"+sliceIndex);
        var formData = new FormData();
        formData.append('token',token);
        formData.append("file", chunk, filename);
        formData.append("totalPieces", totalPieces);
        formData.append("index", index);
        $.ajax({
            url: "videoUploadController/upload",
            type: "POST",
            async:false,
            cache: false,
            data: formData,
            processData: false,
            contentType: false,
        }).done(function(res) {
            
            tempsFile.push(res.msg);
            originalFilePath = res.message;
            
            // 进度条
             pecent=100*(end)/filesize;
             if(pecent>100){
                  pecent=100;
            }
             progressBar.style.width=pecent+'%';
             progressBar.innerHTML = parseInt(pecent)+'%';
             
        }).fail(function(res) {
            alert('文件发送失败,请重新发送');
            progressBar.style.width='0%';
        });
        start = end;
        index ++;
    }
    merge(tempsFile, originalFilePath);
    console.log("上传成功");
}

 
function merge(tempsFile, originalFilePath) {
    $.ajax({
        url:"videoUploadController/merge",
        dataType:"json",
        async:false,
        data:{"token":token, "originalFilePath":originalFilePath, "tempsFile": tempsFile},
        type:"POST",
        beforeSend:function(){
            //请求前的处理
        },
        success:function(req){
            
        },
        complete:function(){
            //请求完成的处理
        },
        error:function(){
            //请求出错处理
        }
    });
} 

</script>
</body>
</html>

 

posted @ 2017-11-14 09:32  飘絮不飘  阅读(1637)  评论(0编辑  收藏  举报