• php b/s批量下载文件


    需求:

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

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

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

    服务器不需要打包。

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

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

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

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

    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/

  • 相关阅读:
    android之PackageManager简单介绍
    OUI-67076 : OracleHomeInventory was not able to create a lock file&quot; in Unix
    编程之美2013 初赛一 A
    Unity3D之挥动武器产生的剑痕特效
    怎样在万网加入Lync Online SRV记录
    mysql-定时调用存储过程
    在TextView中加入图片
    shell语法简单介绍
    quick-cocos2d-x android返回键监听并实现原生退出对话框
    秒杀多线程第四篇 一个经典的多线程同步问题
  • 原文地址:https://www.cnblogs.com/songsu/p/13360900.html
Copyright © 2020-2023  润新知