首页 > 其他分享 >单文件WebUploader做大文件的分块和断点续传

单文件WebUploader做大文件的分块和断点续传

时间:2023-11-17 14:13:08浏览次数:36  
标签:文件 File 分块 fileMd5 WebUploader 断点续传 file 上传

前言:

WebUploader是由Baidu WebFE(FEX)团队开发的一个简单的以HTML5为主,FLASH为辅的现代文件上传组件。在现代的浏览器里面能充分发挥HTML5的优势,同时又不摒弃主流IE浏览器,沿用原来的FLASH运行时,兼容IE6+,iOS 6+, android 4+。两套运行时,同样的调用方式,可供用户任意选用。

 

上面的一段话是来自 http://fex.baidu.com/webuploader/  的介绍,现在做的项目需要用到大文件的上传,之前没有做过,现有的jquery的uploadify只用于上传图片什么的小文件,查了网上的资料,这个插件好像对于大文件不是很友好,为了安全起见,使用百度的成熟框架,不论是多文件还是单个的大文件都是很好用的,没有很多的问题,关于webuploader的详细介绍看官网就行:

 

我的项目是javaweb,开发环境是MyEclipse,页面使用jsp

 

1、先将 webuploader-0.1.5.zip 这个文件下载下来:https://github.com/fex-team/webuploader/releases  

根据个人的需求放置自己需要的东西就行,全部放到项目里也可以,下面是我自己需要的东西:

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


1、jsp部分代码:

 

  1. <script type="text/javascript">  
  2.         var fileMd5;  
  3.         //监听分块上传过程中的三个时间点  
  4.         WebUploader.Uploader.register({  
  5.             "before-send-file":"beforeSendFile",  
  6.             "before-send":"beforeSend",  
  7.             "after-send-file":"afterSendFile",  
  8.         },{  
  9.             //时间点1:所有分块进行上传之前调用此函数  
  10.             beforeSendFile:function(file){  
  11.                 var deferred = WebUploader.Deferred();  
  12.                 //1、计算文件的唯一标记,用于断点续传  
  13.                 (new WebUploader.Uploader()).md5File(file,0,10*1024*1024)  
  14.                     .progress(function(percentage){  
  15.                         $('#item1').find("p.state").text("正在读取文件信息...");  
  16.                     })  
  17.                     .then(function(val){  
  18.                         fileMd5=val;  
  19.                         $('#item1').find("p.state").text("成功获取文件信息...");  
  20.                         //获取文件信息后进入下一步  
  21.                         deferred.resolve();  
  22.                     });  
  23.                 return deferred.promise();  
  24.             },  
  25.             //时间点2:如果有分块上传,则每个分块上传之前调用此函数  
  26.             beforeSend:function(block){  
  27.                 var deferred = WebUploader.Deferred();  
  28.                   
  29.                 $.ajax({  
  30.                     type:"POST",  
  31.                     url:"<%=basePath%>Video?action=checkChunk",  
  32.                     data:{  
  33.                         //文件唯一标记  
  34.                         fileMd5:fileMd5,  
  35.                         //当前分块下标  
  36.                         chunk:block.chunk,  
  37.                         //当前分块大小  
  38.                         chunkSize:block.end-block.start  
  39.                     },  
  40.                     dataType:"json",  
  41.                     success:function(response){  
  42.                         if(response.ifExist){  
  43.                             //分块存在,跳过  
  44.                             deferred.reject();  
  45.                         }else{  
  46.                             //分块不存在或不完整,重新发送该分块内容  
  47.                             deferred.resolve();  
  48.                         }  
  49.                     }  
  50.                 });  
  51.                   
  52.                 this.owner.options.formData.fileMd5 = fileMd5;  
  53.                 deferred.resolve();  
  54.                 return deferred.promise();  
  55.             },  
  56.             //时间点3:所有分块上传成功后调用此函数  
  57.             afterSendFile:function(){  
  58.                 //如果分块上传成功,则通知后台合并分块  
  59.                 $.ajax({  
  60.                     type:"POST",  
  61.                     url:"<%=basePath%>Video?action=mergeChunks",  
  62.                     data:{  
  63.                         fileMd5:fileMd5,  
  64.                     },  
  65.                     success:function(response){  
  66.                         alert("上传成功");  
  67.                         var path = "uploads/"+fileMd5+".mp4";  
  68.                         $("#item1").attr("src",path);  
  69.                     }  
  70.                 });  
  71.             }  
  72.         });  
  73.           
  74.         var uploader = WebUploader.create({  
  75.             // swf文件路径  
  76.             swf: '<%=basePath%>scripts/webuploader-0.1.5/Uploader.swf',  
  77.             // 文件接收服务端。  
  78.             server: '<%=basePath%>UploadVideo',  
  79.             // 选择文件的按钮。可选。  
  80.             // 内部根据当前运行是创建,可能是input元素,也可能是flash.  
  81.             pick: {id: '#add_video',   <span style="background-color:rgb(255,204,0);">//这个id是你要点击上传文件的id,自己设置就好</span>  
  82.             multiple:false},  
  83.             // 不压缩image, 默认如果是jpeg,文件上传前会压缩一把再上传!  
  84.             resize: true,  
  85.             auto:true,  
  86.             //开启分片上传  
  87.             chunked: true,  
  88.             chunkSize:10*1024*1024,  
  89.               
  90.             accept: {  
  91.             //限制上传文件为MP4  
  92.                 extensions: 'mp4',  
  93.                 mimeTypes: 'video/mp4',  
  94.             }  
  95.         });  
  96.                   
  97.         // 当有文件被添加进队列的时候  
  98.         uploader.on( 'fileQueued', function( file ) {  
  99.               
  100.             $('#item1').empty();  
  101.             $('#item1').html('<div id="' + file.id + '" class="item">'+  
  102.                 '<a class="upbtn" id="btn" onclick="stop()">[取消上传]</a>'+  
  103.                 '<p class="info">' + file.name + '</p>' +  
  104.                 '<p class="state">等待上传...</p></div>'  
  105.             );  
  106.         });  
  107.           
  108.         // 文件上传过程中创建进度条实时显示。  
  109.         uploader.on( 'uploadProgress', function( file, percentage ) {  
  110.             $('#item1').find('p.state').text('上传中 '+Math.round(percentage * 100) + '%');  
  111.         });  
  112.           
  113.         uploader.on( 'uploadSuccess', function( file ) {  
  114.             $( '#'+file.id ).find('p.state').text('已上传');  
  115.         });  
  116.           
  117.         uploader.on( 'uploadError', function( file ) {  
  118.             $( '#'+file.id ).find('p.state').text('上传出错');  
  119.         });  
  120.           
  121.         uploader.on( 'uploadComplete', function( file ) {  
  122.             $( '#'+file.id ).find('.progress').fadeOut();  
  123.         });  
  124.         
  125.         function start(){  
  126.             uploader.upload();  
  127.             $('#btn').attr("onclick","stop()");  
  128.             $('#btn').text("取消上传");  
  129.         }  
  130.           
  131.         function stop(){  
  132.             uploader.stop(true);  
  133.             $('#btn').attr("onclick","start()");  
  134.             $('#btn').text("继续上传");  
  135.         }  
  136.           
  137.     </script>  

 

 

2、servlet部分代码:


servlet部分需要两个servlet,一个用于接收分块文件,一个用于合并分块成一个文件:

1、接收分块servlet代码:

 

  1. @SuppressWarnings("serial")  
  2. public class UploadVideo extends HttpServlet {  
  3.     @Override  
  4.     protected void doGet(HttpServletRequest req, HttpServletResponse resp)  
  5.             throws ServletException, IOException {  
  6.         // TODO Auto-generated method stub  
  7.         super.doGet(req, resp);  
  8.         doPost(req, resp);  
  9.     }  
  10.     @SuppressWarnings("unchecked")  
  11.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  12.             throws ServletException, IOException {  
  13.           
  14.         DiskFileItemFactory factory = new DiskFileItemFactory();  
  15.         ServletFileUpload sfu = new ServletFileUpload(factory);  
  16.         sfu.setHeaderEncoding("utf-8");  
  17.           
  18.         String savePath = this.getServletConfig().getServletContext()  
  19.                 .getRealPath("");  
  20.         String folad = "uploads";  
  21.         savePath = savePath + "\\"+folad+"\\";  
  22.           
  23.         String fileMd5 = null;  
  24.         String chunk = null;  
  25.           
  26.         try {  
  27.             List<FileItem> items = sfu.parseRequest(request);  
  28.               
  29.             for(FileItem item:items){  
  30.                 if(item.isFormField()){  
  31.                     String fieldName = item.getFieldName();  
  32.                     if(fieldName.equals("fileMd5")){  
  33.                         fileMd5 = item.getString("utf-8");  
  34.                     }  
  35.                     if(fieldName.equals("chunk")){  
  36.                         chunk = item.getString("utf-8");  
  37.                     }  
  38.                 }else{  
  39.                     File file = new File(savePath+"/"+fileMd5);  
  40.                     if(!file.exists()){  
  41.                         file.mkdir();  
  42.                     }  
  43.                     File chunkFile = new File(savePath+"/"+fileMd5+"/"+chunk);  
  44.                     FileUtils.copyInputStreamToFile(item.getInputStream(), chunkFile);  
  45.                       
  46.                 }  
  47.             }  
  48.               
  49.         } catch (FileUploadException e) {  
  50.             // TODO Auto-generated catch block  
  51.             e.printStackTrace();  
  52.         }  
  53.           
  54.     }  
  55. }  

 

 

2、合并分块servlet代码:

 

  1. @SuppressWarnings("serial")  
  2. public class Video extends HttpServlet {  
  3.   
  4.     public void doGet(HttpServletRequest request, HttpServletResponse response)  
  5.             throws ServletException, IOException {  
  6.         super.doGet(request, response);  
  7.         doPost(request, response);  
  8.           
  9.     }  
  10.   
  11.     public void doPost(HttpServletRequest request, HttpServletResponse response)  
  12.             throws ServletException, IOException {  
  13.         String savePath = this.getServletConfig().getServletContext()  
  14.                 .getRealPath("");  
  15.         String folad = "uploads";  
  16.         savePath = savePath + "\\"+folad+"\\";  
  17.           
  18.         String action = request.getParameter("action");  
  19.           
  20.         if(action.equals("mergeChunks")){  
  21.             //合并文件  
  22.             //需要合并的文件的目录标记  
  23.             String fileMd5 = request.getParameter("fileMd5");  
  24.               
  25.             //读取目录里的所有文件  
  26.             File f = new File(savePath+"/"+fileMd5);  
  27.             File[] fileArray = f.listFiles(new FileFilter(){  
  28.                 //排除目录只要文件  
  29.                 @Override  
  30.                 public boolean accept(File pathname) {  
  31.                     // TODO Auto-generated method stub  
  32.                     if(pathname.isDirectory()){  
  33.                         return false;  
  34.                     }  
  35.                     return true;  
  36.                 }  
  37.             });  
  38.               
  39.             //转成集合,便于排序  
  40.             List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));  
  41.             Collections.sort(fileList,new Comparator<File>() {  
  42.                 @Override  
  43.                 public int compare(File o1, File o2) {  
  44.                     // TODO Auto-generated method stub  
  45.                     if(Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())){  
  46.                         return -1;  
  47.                     }  
  48.                     return 1;  
  49.                 }  
  50.             });  
  51.             //UUID.randomUUID().toString()-->随机名  
  52.             File outputFile = new File(savePath+"/"+fileMd5+".mp4");  
  53.             //创建文件  
  54.             outputFile.createNewFile();  
  55.             //输出流  
  56.             FileChannel outChnnel = new FileOutputStream(outputFile).getChannel();  
  57.             //合并  
  58.             FileChannel inChannel;  
  59.             for(File file : fileList){  
  60.                 inChannel = new FileInputStream(file).getChannel();  
  61.                 inChannel.transferTo(0, inChannel.size(), outChnnel);  
  62.                 inChannel.close();  
  63.                 //删除分片  
  64.                 file.delete();  
  65.             }  
  66.             outChnnel.close();  
  67.             //清除文件夹  
  68.             File tempFile = new File(savePath+"/"+fileMd5);  
  69.             if(tempFile.isDirectory() && tempFile.exists()){  
  70.                 tempFile.delete();  
  71.             }  
  72.             System.out.println("合并成功");  
  73.         }else if(action.equals("checkChunk")){  
  74.             //检查当前分块是否上传成功  
  75.             String fileMd5 = request.getParameter("fileMd5");  
  76.             String chunk = request.getParameter("chunk");  
  77.             String chunkSize = request.getParameter("chunkSize");  
  78.               
  79.             File checkFile = new File(savePath+"/"+fileMd5+"/"+chunk);  
  80.               
  81.             response.setContentType("text/html;charset=utf-8");  
  82.             //检查文件是否存在,且大小是否一致  
  83.             if(checkFile.exists() && checkFile.length()==Integer.parseInt(chunkSize)){  
  84.                 //上传过  
  85.                 response.getWriter().write("{\"ifExist\":1}");  
  86.             }else{  
  87.                 //没有上传过  
  88.                 response.getWriter().write("{\"ifExist\":0}");  
  89.             }  
  90.         }  
  91.           
  92.     }  
  93.   
  94. }  

 

 

至此,大文件上传的分块和断点就ok了,这也只是我自己的项目需求编写的,这个框架还涵盖很多的内容和功能,需要你自己去研究了,不过都不是很难,你也可以去修改它的css和js文件根据自己的需求。

 

参考文章:http://blog.ncmem.com/wordpress/2023/11/17/%e5%8d%95%e6%96%87%e4%bb%b6webuploader%e5%81%9a%e5%a4%a7%e6%96%87%e4%bb%b6%e7%9a%84%e5%88%86%e5%9d%97%e5%92%8c%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/

欢迎入群一起讨论

 

 

标签:文件,File,分块,fileMd5,WebUploader,断点续传,file,上传
From: https://www.cnblogs.com/songsu/p/17838594.html

相关文章

  • 安装 IIS 访问临时文件夹 C:\WINDOWS\TEMP\3C 读取/写入权限 错误: 0x80070005
    在windows中使用命令行方式安装IIS(Web服务器)WindowsServer2022安装IIS报错访问临时文件夹C:\WINDOWS\TEMP\3C读取/写入权限错误:0x80070005,可以使用命令行方式来安装和配置Web服务(IIS)。以下是使用DeploymentImageServicingandManagement(DISM)工具的步骤:1.打......
  • 大文件上传的处理方法——切片上传
    本篇介绍了切片上传的基本实现方式,以及实现切片上传后的一些附加功能,切片上传原理较为简单,代码注释比较清晰就不多赘述了,后面的附加功能介绍了实现原理,并贴出了在原本代码上的改进方式。有什么错误希望大佬可以指出,感激不尽。切片后上传切片上传的原理较为简单,即获取文件后切片,切片......
  • 前端大文件上传如何做到刷新续传?
    前言这两天在学习阿里云oss上传。踩了不少坑,终于实现了大文件分片、断点续传的功能。这篇文章主要分享学习笔记,希望能给大家一些帮助。先看效果 技术栈1.前端:react+Ts+axios上传文件2.Node部分:定义接口、阿里云oss3.socket.io:实时同步上传进度特别说明axios中onUploadPr......
  • java如何做大体积的文件上传和下载
    在Java中,实现大体积文件的上传和下载涉及到处理文件的分片、并发上传、断点续传等问题。本文将详细介绍如何通过Java实现大体积文件的上传和下载。1.文件上传文件上传是将本地文件上传到服务器的过程。对于大体积文件的上传,我们可以将文件分成多个小片段进行并发上传。1.1文件分......
  • 前端如何实现大文件上传
    在开发过程中,经常会遇到一些较大文件上传,如果只使用一次请求去上传文件,一旦这次请求中出现什么问题,那么无论这次上传了多少文件,都会失去效果,用户则需要重新上传所有资源。所以就想到一种方式,将一个大文件分成多个小文件,这样通过多个请求实现大文件上传。接下来我们就来看看具体是怎......
  • Git与Gitee的交互及配置忽略文件
    将本地项目提交到Gitee1、创建一个新的仓库:首先,在Gitee上创建一个新的仓库。2、初始化本地项目为Git仓库:这将在项目目录中创建一个名为".git"的隐藏文件夹,用于存储Git的相关配置和版本信息。gitinit3、将项目文件添加到暂存区:执行以下命令将项目文件添加到Git的暂存区:   ......
  • HTML5中怎么实现文件断点续传功能
    HTML5中怎么实现文件断点续传功能,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。断点续传原理目前比较常用的断点续传的方法有两种,一种是通过websocket接口进行文件上传,另一种是通过ajax,两种方法各有千秋......
  • 大文件断点续传上传
    最近接到一个新的需求,需要上传2G左右的视频文件,用测试环境的OSS试了一下,上传需要十几分钟,再考虑到公司的资源问题,果断放弃该方案。一提到大文件上传,我最先想到的就是各种网盘了,现在大家都喜欢将自己收藏的「小电影」上传到网盘进行保存。网盘一般都支持断点续传和文件秒传功能,减少......
  • 通过Java实现文件断点续传功能
    用户上传大文件,网络差点的需要历时数小时,万一线路中断,不具备断点续传的服务器就只能从头重传,而断点续传就是,允许用户从上传断线的地方继续传送,这样大大减少了用户的烦恼。本文将用Java语言实现断点续传,需要的可以参考一下什么是断点续传用户上传大文件,网络差点的需要历时数小时,万......
  • webuploader实现大文件断点续传
    前端代码(基于Yii框架,逻辑可供参考)   <script>    varfileMd5; //文件MD5    varfileObj; //文件对象    varstate='pending'; //状态    WebUploader.Uploader.register({      "before-send":"beforeSend......