zoukankan      html  css  js  c++  java
  • B/S大文件下载+断点续传

    1、先将 webuploader-0.1.5.zip 这个文件下载下来:https://github.com/fex-team/webuploader/releases  
    根据个人的需求放置自己需要的东西就行,全部放到项目里也可以,下面是我自己需要的东西:



    2、代码部分:分为jsp和servlet部分

    1、jsp部分代码:
     
    <script type="text/javascript">
            var fileMd5;
            //监听分块上传过程中的三个时间点
            WebUploader.Uploader.register({
            "before-send-file":"beforeSendFile",
            "before-send":"beforeSend",
            "after-send-file":"afterSendFile",
            },{
            //时间点1:所有分块进行上传之前调用此函数
            beforeSendFile:function(file){
            var deferred = WebUploader.Deferred();
            //1、计算文件的唯一标记,用于断点续传
            (new WebUploader.Uploader()).md5File(file,0,10*1024*1024)
            .progress(function(percentage){
            $('#item1').find("p.state").text("正在读取文件信息...");
            })
            .then(function(val){
            fileMd5=val;
            $('#item1').find("p.state").text("成功获取文件信息...");
            //获取文件信息后进入下一步
            deferred.resolve();
            });
            return deferred.promise();
            },
            //时间点2:如果有分块上传,则每个分块上传之前调用此函数
            beforeSend:function(block){
            var deferred = WebUploader.Deferred();
            $.ajax({
            type:"POST",
            url:"<%=basePath%>Video?action=checkChunk",
            data:{
            //文件唯一标记
            fileMd5:fileMd5,
            //当前分块下标
            chunk:block.chunk,
            //当前分块大小
            chunkSize:block.end-block.start
            },
            dataType:"json",
            success:function(response){
            if(response.ifExist){
            //分块存在,跳过
            deferred.reject();
            }else{
            //分块不存在或不完整,重新发送该分块内容
            deferred.resolve();
            }
            }
            });
            this.owner.options.formData.fileMd5 = fileMd5;
            deferred.resolve();
            return deferred.promise();
            },
            //时间点3:所有分块上传成功后调用此函数
            afterSendFile:function(){
            //如果分块上传成功,则通知后台合并分块
            $.ajax({
            type:"POST",
            url:"<%=basePath%>Video?action=mergeChunks",
            data:{
            fileMd5:fileMd5,
            },
            success:function(response){
            alert("上传成功");
                      var path = "uploads/"+fileMd5+".mp4";
                      $("#item1").attr("src",path);
            }
            });
            }
            });
            var uploader = WebUploader.create({
       // swf文件路径
       swf: '<%=basePath%>scripts/webuploader-0.1.5/Uploader.swf',
       // 文件接收服务端。
       server: '<%=basePath%>UploadVideo',
       // 选择文件的按钮。可选。
       // 内部根据当前运行是创建,可能是input元素,也可能是flash.
       pick: {id: '#add_video',   //这个id是你要点击上传文件的id,自己设置就好
       multiple:false},
       // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
       resize: true,
       auto:true,
       //开启分片上传
       chunked: true,
       chunkSize:10*1024*1024,
       accept: {
       //限制上传文件为MP4
                extensions: 'mp4',
                mimeTypes: 'video/mp4',
            }
    });
            // 当有文件被添加进队列的时候
    uploader.on( 'fileQueued', function( file ) {
    $('#item1').empty();
       $('#item1').html('<div id="' + file.id + '" class="item">'+
        '<a class="upbtn" id="btn" onclick="stop()">[取消上传]</a>'+
        '<p class="info">' + file.name + '</p>' +
           '<p class="state">等待上传...</p></div>'
       );
    });
    // 文件上传过程中创建进度条实时显示。
    uploader.on( 'uploadProgress', function( file, percentage ) {
       $('#item1').find('p.state').text('上传中 '+Math.round(percentage * 100) + '%');
    });
    uploader.on( 'uploadSuccess', function( file ) {
       $( '#'+file.id ).find('p.state').text('已上传');
    });
    uploader.on( 'uploadError', function( file ) {
       $( '#'+file.id ).find('p.state').text('上传出错');
    });
    uploader.on( 'uploadComplete', function( file ) {
       $( '#'+file.id ).find('.progress').fadeOut();
    });
          function start(){
    uploader.upload();
    $('#btn').attr("onclick","stop()");
    $('#btn').text("取消上传");
    }
    function stop(){
    uploader.stop(true);
    $('#btn').attr("onclick","start()");
    $('#btn').text("继续上传");
    }
        </script>
    //这个id是你要点击上传文件的id,自己设置就好
       multiple:false},
       // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!
       resize: true,
       auto:true,
       //开启分片上传
       chunked: true,
       chunkSize:10*1024*1024,
       
       accept: {
       //限制上传文件为MP4
                extensions: 'mp4',
                mimeTypes: 'video/mp4',
            }
    });
           
            // 当有文件被添加进队列的时候
    uploader.on( 'fileQueued', function( file ) {

    $('#item1').empty();
       $('#item1').html('<div id="' + file.id + '" class="item">'+
        '<a class="upbtn" id="btn" onclick="stop()">[取消上传]</a>'+
        '<p class="info">' + file.name + '</p>' +
           '<p class="state">等待上传...</p></div>'
       );
    });

    // 文件上传过程中创建进度条实时显示。
    uploader.on( 'uploadProgress', function( file, percentage ) {
       $('#item1').find('p.state').text('上传中 '+Math.round(percentage * 100) + '%');
    });

    uploader.on( 'uploadSuccess', function( file ) {
       $( '#'+file.id ).find('p.state').text('已上传');
    });

    uploader.on( 'uploadError', function( file ) {
       $( '#'+file.id ).find('p.state').text('上传出错');
    });

    uploader.on( 'uploadComplete', function( file ) {
       $( '#'+file.id ).find('.progress').fadeOut();
    });
          
          function start(){
    uploader.upload();
    $('#btn').attr("onclick","stop()");
    $('#btn').text("取消上传");
    }

    function stop(){
    uploader.stop(true);
    $('#btn').attr("onclick","start()");
    $('#btn').text("继续上传");
    }
            
        </script>
     
     
     
    2、servlet部分代码:

    servlet部分需要两个servlet,一个用于接收分块文件,一个用于合并分块成一个文件:
    1、接收分块servlet代码:
     
    @SuppressWarnings("serial")
    public class UploadVideo extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp)
    throws ServletException, IOException {
    // TODO Auto-generated method stub
    super.doGet(req, resp);
    doPost(req, resp);
    }
        @SuppressWarnings("unchecked")
        public void doPost(HttpServletRequest request, HttpServletResponse response)
                throws ServletException, IOException {
        DiskFileItemFactory factory = new DiskFileItemFactory();
        ServletFileUpload sfu = new ServletFileUpload(factory);
        sfu.setHeaderEncoding("utf-8");
        String savePath = this.getServletConfig().getServletContext()
                    .getRealPath("");
            String folad = "uploads";
            savePath = savePath + "\"+folad+"\";
        String fileMd5 = null;
        String chunk = null;
        try {
    List<FileItem> items = sfu.parseRequest(request);
    for(FileItem item:items){
    if(item.isFormField()){
    String fieldName = item.getFieldName();
    if(fieldName.equals("fileMd5")){
    fileMd5 = item.getString("utf-8");
    }
    if(fieldName.equals("chunk")){
    chunk = item.getString("utf-8");
    }
    }else{
    File file = new File(savePath+"/"+fileMd5);
    if(!file.exists()){
    file.mkdir();
    }
    File chunkFile = new File(savePath+"/"+fileMd5+"/"+chunk);
    FileUtils.copyInputStreamToFile(item.getInputStream(), chunkFile);
    }
    }
    } catch (FileUploadException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
        }
    }
     
     
     
    2、合并分块servlet代码:
     
    @SuppressWarnings("serial")
    public class Video extends HttpServlet {
    public void doGet(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    super.doGet(request, response);
    doPost(request, response);
    }
    public void doPost(HttpServletRequest request, HttpServletResponse response)
    throws ServletException, IOException {
    String savePath = this.getServletConfig().getServletContext()
                    .getRealPath("");
            String folad = "uploads";
            savePath = savePath + "\"+folad+"\";
    String action = request.getParameter("action");
    if(action.equals("mergeChunks")){
    //合并文件
    //需要合并的文件的目录标记
    String fileMd5 = request.getParameter("fileMd5");
    //读取目录里的所有文件
    File f = new File(savePath+"/"+fileMd5);
    File[] fileArray = f.listFiles(new FileFilter(){
    //排除目录只要文件
    @Override
    public boolean accept(File pathname) {
    // TODO Auto-generated method stub
    if(pathname.isDirectory()){
    return false;
    }
    return true;
    }
    });
    //转成集合,便于排序
    List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
    Collections.sort(fileList,new Comparator<File>() {
    @Override
    public int compare(File o1, File o2) {
    // TODO Auto-generated method stub
    if(Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())){
    return -1;
    }
    return 1;
    }
    });
    //UUID.randomUUID().toString()-->随机名
    File outputFile = new File(savePath+"/"+fileMd5+".mp4");
    //创建文件
    outputFile.createNewFile();
    //输出流
    FileChannel outChnnel = new FileOutputStream(outputFile).getChannel();
    //合并
    FileChannel inChannel;
    for(File file : fileList){
    inChannel = new FileInputStream(file).getChannel();
    inChannel.transferTo(0, inChannel.size(), outChnnel);
    inChannel.close();
    //删除分片
    file.delete();
    }
    outChnnel.close();
    //清除文件夹
    File tempFile = new File(savePath+"/"+fileMd5);
    if(tempFile.isDirectory() && tempFile.exists()){
    tempFile.delete();
    }
    System.out.println("合并成功");
    }else if(action.equals("checkChunk")){
    //检查当前分块是否上传成功
    String fileMd5 = request.getParameter("fileMd5");
    String chunk = request.getParameter("chunk");
    String chunkSize = request.getParameter("chunkSize");
    File checkFile = new File(savePath+"/"+fileMd5+"/"+chunk);
    response.setContentType("text/html;charset=utf-8");
    //检查文件是否存在,且大小是否一致
    if(checkFile.exists() && checkFile.length()==Integer.parseInt(chunkSize)){
    //上传过
    response.getWriter().write("{"ifExist":1}");
    }else{
    //没有上传过
    response.getWriter().write("{"ifExist":0}");
    }
    }
    }
    }
     
     
     
    至此,大文件上传的分块和断点就ok了,这也只是我自己的项目需求编写的,这个框架还涵盖很多的内容和功能,需要你自己去研究了,不过都不是很难,你也可以去修改它的css和js文件根据自己的需求。
    详细的配置信息可以参考我写的这篇文章:http://blog.ncmem.com/wordpress/2019/08/28/java%E6%89%B9%E9%87%8F%E4%B8%8B%E8%BD%BD/ 

    欢迎入群一起讨论:374992201

  • 相关阅读:
    sell学习
    redis安装
    [Yii Framework] Share the session with memcache in Yii
    CentOS 网络设置修改
    虚拟机的几种网络方式详解
    linux命令小技巧
    交叉编译: 常见参数配置
    Extend volumn in ubuntu 14.04
    OpenCV 2.4.13 installed in Ubuntu 14 and CMakeLists Demo
    CMake: Cross-Platform Compling
  • 原文地址:https://www.cnblogs.com/songsu/p/11460520.html
Copyright © 2011-2022 走看看