php b/s批量下载文件

需求:

文件批量上传,支持断点续传。

文件批量下载,支持断点续传。

使用JS能够实现批量下载,能够提供接口从指定url中下载文件并保存在本地指定路径中。

服务器不需要打包。

支持大文件断点下载。比如下载10G的文件。

PC端全平台支持。Windows,macOS,Linux

全浏览器支持。ie6,ie7,ie8,ie9,ie10,ie11,edge,firefox,chrome,safari

 

1、先将 down2 这个示例和控件下载下来,根据个人的需求放置自己需要的东西就行,全部放到项目里也可以,下面是我自己需要的东西:

php b/s批量下载文件php b/s批量下载文件

 

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/06/14/java%e6%89%b9%e9%87%8f%e4%b8%8b%e8%bd%bd%e6%96%87%e4%bb%b6%e5%88%b0%e6%8c%87%e5%ae%9a%e6%96%87%e4%bb%b6%e5%a4%b9/

 

php b/s批量下载文件

上一篇:Spring学习(二)——使用用Gradle构建一个简单的Spring MVC Web应用程序


下一篇:廖雪峰python教程实战-DAY2编写Web APP骨架