单文件WebUploader做大文件的分块和断点续传
前言:
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部分代码:
- <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', <span style="background-color:rgb(255,204,0);">//这个id是你要点击上传文件的id,自己设置就好</span>
- 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文件根据自己的需求。
单文件WebUploader做大文件的分块和断点续传的更多相关文章
- php使用WebUploader做大文件的分块和断点续传
核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...
- js使用WebUploader做大文件的分块和断点续传
1 背景 用户本地有一份txt或者csv文件,无论是从业务数据库导出.还是其他途径获取,当需要使用蚂蚁的大数据分析工具进行数据加工.挖掘和共创应用的时候,首先要将本地文件上传至ODPS,普通的小文件通 ...
- java使用WebUploader做大文件的分块和断点续传
版权所有 2009-2018荆门泽优软件有限公司 保留所有权利 官方网站:http://www.ncmem.com/ 产品首页:http://www.ncmem.com/webapp/up6.2/in ...
- .net使用WebUploader做大文件的分块和断点续传
ASP.NET上传文件用FileUpLoad就可以,但是对文件夹的操作却不能用FileUpLoad来实现. 下面这个示例便是使用ASP.NET来实现上传文件夹并对文件夹进行压缩以及解压. ASP.NE ...
- asp.net使用WebUploader做大文件的分块和断点续传
HTML部分 <%@ Page Language="C#" AutoEventWireup="true" CodeBehind="index.a ...
- 使用webuploader实现大文件断点续传
IE的自带下载功能中没有断点续传功能,要实现断点续传功能,需要用到HTTP协议中鲜为人知的几个响应头和请求头. 一. 两个必要响应头Accept-Ranges.ETag 客户端每次提交下载请求时,服务 ...
- java读取 500M 以上文件,java读取大文件
java 读取txt,java读取大文件 设置缓存大小BUFFER_SIZE ,Config.tempdatafile是文件地址 来源博客http://yijianfengvip.blog.163.c ...
- webUploader实现大文件分片,断点续传
问题: 公司现在的业务需求是要上传一个大文件,上一次写了一篇博客,做了一个简单的文件上传,支持单文件,大型文件上传 现在对之前的上传进行优化,支持断点续传,秒传功能 上次博客:[http://www. ...
- ASP.NET CORE使用WebUploader对大文件分片上传,并通过ASP.NET CORE SignalR实时反馈后台处理进度给前端展示
本次,我们来实现一个单个大文件上传,并且把后台对上传文件的处理进度通过ASP.NET CORE SignalR反馈给前端展示,比如上传一个大的zip压缩包文件,后台进行解压缩,并且对压缩包中的文件进行 ...
随机推荐
- python中使用rsa加密
前提不多说, 为什么使用RSA加密请自行搜索,直接正为: 一. 生成公钥及私钥, 并保存 二. 使用公钥加密, 私钥解密 后记: 通常使用中, 会先对数据进行bas64加密, 再对加密后的内容使用rs ...
- Linux性能优化实战学习笔记:第四十七讲
一.上节回顾 上一节,我们梳理了,应用程序容器化后性能下降的分析方法.一起先简单回顾下.容器利用 Linux 内核提供的命名空间技术,将不同应用程序的运行隔离起来,并用统一的镜像,来管理应用程序的依赖 ...
- MySQL实战45讲学习笔记:第二十八讲
一.读写分离架构 在上一篇文章中,我和你介绍了一主多从的结构以及切换流程.今天我们就继续聊聊一主多从架构的应用场景:读写分离,以及怎么处理主备延迟导致的读写分离问题. 我们在上一篇文章中提到的一主多从 ...
- Ubuntu16LTS使用笔记(Server版)
环境测试:Ubuntu Server 16.04.06 x64 虚拟机 以下均需要root权限,请sudo 或 su root 解决只有先启动Windows再重启到Linux才能使用usb网卡的问题: ...
- 基于sign的pose-graph残差函数构建
沿sign的法线方向优化车辆位姿,优化目标函数也即残差函数构建过程如下:
- TPM(ThinkPHPMobile)使用简明教程
TPM还有很多特性,它不仅能和ThinkPHP结合,也可以结合自己已有的接口.还有一些附件插件帮助我们实现一些常用功能 一.基础知识 1 手机APP的类型 移动端的应用有这几种:WebApp,Nati ...
- 出师表(ENGLISH) 强烈打call啊~王洛勇是什么神仙英语
臣亮言:先帝创业未半而中道崩殂, Permit me to observe: the late emperor was taken from us before he could finish his ...
- Web应急:网站首页被篡改
网站首页被非法篡改,是的,就是你一打开网站就知道自己的网站出现了安全问题,网站程序存在严重的安全漏洞,攻击者通过上传脚本木马,从而对网站内容进行篡改.而这种篡改事件在某些场景下,会被无限放大. 现象描 ...
- 【leetcode-148】排序链表
在 O(n log n) 时间复杂度和常数级空间复杂度下,对链表进行排序. 示例 1: 输入: 4->2->1->3输出: 1->2->3->4示例 2: 输入: ...
- Java反射复习
三种实例化对象: 1.Class<?> cls = Class.forName("java.util.Date") ; *** System.out.println(c ...