首页 > 编程语言 >Java实现浏览器端大文件分片上传技术

Java实现浏览器端大文件分片上传技术

时间:2023-07-12 14:00:11浏览次数:48  
标签:function 文件 Java 端大 源码 分片 上传 id fileSvr

 javaweb上传文件

上传文件的jsp中的部分

上传文件同样可以使用form表单向后端发请求,也可以使用 ajax向后端发请求

    1.通过form表单向后端发送请求

         <form id="postForm" action="${pageContext.request.contextPath}/UploadServlet" method="post" enctype="multipart/form-data">

            <div class="bbxx wrap">

                <inputtype="text" id="side-profile-name" name="username" class="form-control">

                <inputtype="file" id="example-file-input" name="avatar">

                <button type="submit" class="btn btn-effect-ripple btn-primary">Save</button>

            </div>

        </form>

改进后的代码不需要form标签,直接由控件来实现。开发人员只需要关注业务逻辑即可。JS中已经帮我们封闭好了

    this.post_file = function ()

    {

        $.each(this.ui.btn, function (i, n) { n.hide();});

        this.ui.btn.stop.show();

        this.State = this.Config.state.Posting;//

        this.app.postFile({ id: this.fileSvr.id, pathLoc: this.fileSvr.pathLoc, pathSvr:this.fileSvr.pathSvr,lenSvr: this.fileSvr.lenSvr, fields: this.fields });

    };

通过监控工具可以看到控件提交的数据,非常的清晰,调试也非常的简单。

2.通过ajax向后端发送请求

            $.ajax({

                 url : "${pageContext.request.contextPath}/UploadServlet",

                 type : "POST",

                 data : $( '#postForm').serialize(),

                 success : function(data) {

                      $( '#serverResponse').html(data);

                 },

                 error : function(data) {

                      $( '#serverResponse').html(data.status + " : " + data.statusText + " : " + data.responseText);

                 }

            });

ajax分为两部分,一部分是初始化,文件在上传前通过AJAX请求通知服务端进行初始化操作

    this.md5_complete = function (json)

    {

        this.fileSvr.md5 = json.md5;

        this.ui.msg.text("MD5计算完毕,开始连接服务器...");

        this.event.md5Complete(this, json.md5);//biz event

 

        var loc_path = encodeURIComponent(this.fileSvr.pathLoc);

        var loc_len = this.fileSvr.lenLoc;

        var loc_size = this.fileSvr.sizeLoc;

        var param = jQuery.extend({}, this.fields, this.Config.bizData, { md5: json.md5, id: this.fileSvr.id, lenLoc: loc_len, sizeLoc: loc_size, pathLoc: loc_path, time: new Date().getTime() });

 

        $.ajax({

            type: "GET"

            , dataType: 'jsonp'

            , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名

            , url: this.Config["UrlCreate"]

            , data: param

            , success: function (sv)

            {

                _this.svr_create(sv);

            }

            , error: function (req, txt, err)

            {

                _this.Manager.RemoveQueuePost(_this.fileSvr.id);

                alert("向服务器发送MD5信息错误!" + req.responseText);

                _this.ui.msg.text("向服务器发送MD5信息错误");

                _this.ui.btn.cancel.show();

                _this.ui.btn.stop.hide();

            }

            , complete: function (req, sta) { req = null; }

        });

    };

 

在文件上传完后向服务器发送通知

    this.post_complete = function (json)

    {

        this.fileSvr.perSvr = "100%";

        this.fileSvr.complete = true;

        $.each(this.ui.btn, function (i, n)

        {

            n.hide();

        });

        this.ui.process.css("width", "100%");

        this.ui.percent.text("(100%)");

        this.ui.msg.text("上传完成");

        this.Manager.arrFilesComplete.push(this);

        this.State = this.Config.state.Complete;

        //从上传列表中删除

        this.Manager.RemoveQueuePost(this.fileSvr.id);

        //从未上传列表中删除

        this.Manager.RemoveQueueWait(this.fileSvr.id);

 

        var param = { md5: this.fileSvr.md5, uid: this.uid, id: this.fileSvr.id, time: new Date().getTime() };

 

        $.ajax({

            type: "GET"

              , dataType: 'jsonp'

              , jsonp: "callback" //自定义的jsonp回调函数名称,默认为jQuery自动生成的随机函数名

              , url: _this.Config["UrlComplete"]

              , data: param

              , success: function (msg)

              {

                  _this.event.fileComplete(_this);//触发事件

                  _this.post_next();

              }

              , error: function (req, txt, err) { alert("文件-向服务器发送Complete信息错误!" + req.responseText); }

              , complete: function (req, sta) { req = null; }

        });

    };

 

这里需要处理一个MD5秒传的逻辑,当服务器存在相同文件时,不需要用户再上传,而是直接通知用户秒传

    this.post_complete_quick = function ()

    {

        this.fileSvr.perSvr = "100%";

        this.fileSvr.complete = true;

        this.ui.btn.stop.hide();

        this.ui.process.css("width", "100%");

        this.ui.percent.text("(100%)");

        this.ui.msg.text("服务器存在相同文件,快速上传成功。");

        this.Manager.arrFilesComplete.push(this);

        this.State = this.Config.state.Complete;

        //从上传列表中删除

        this.Manager.RemoveQueuePost(this.fileSvr.id);

        //从未上传列表中删除

        this.Manager.RemoveQueueWait(this.fileSvr.id);

        //添加到文件列表

        this.post_next();

        this.event.fileComplete(this);//触发事件

    };

这里可以看到秒传的逻辑是非常 简单的,并不是特别的复杂。

            var form = new FormData();

            form.append("username","zxj");

            form.append("avatar",file);

            //var form = new FormData($("#postForm")[0]);

            $.ajax({

                url:"${pageContext.request.contextPath}/UploadServlet",

                type:"post",

                data:form,

                processData:false,

                contentType:false,

                success:function(data){

        

                    console.log(data);

                }

            });

java部分

文件初始化的逻辑,主要代码如下

FileInf fileSvr= new FileInf();

fileSvr.id = id;

fileSvr.fdChild = false;

fileSvr.uid = Integer.parseInt(uid);

fileSvr.nameLoc = PathTool.getName(pathLoc);

fileSvr.pathLoc = pathLoc;

fileSvr.lenLoc = Long.parseLong(lenLoc);

fileSvr.sizeLoc = sizeLoc;

fileSvr.deleted = false;

fileSvr.md5 = md5;

fileSvr.nameSvr = fileSvr.nameLoc;

 

//所有单个文件均以uuid/file方式存储

PathBuilderUuid pb = new PathBuilderUuid();

fileSvr.pathSvr = pb.genFile(fileSvr.uid,fileSvr);

fileSvr.pathSvr = fileSvr.pathSvr.replace("\\","/");

 

DBConfig cfg = new DBConfig();

DBFile db = cfg.db();

FileInf fileExist = new FileInf();

    

boolean exist = db.exist_file(md5,fileExist);

//数据库已存在相同文件,且有上传进度,则直接使用此信息

if(exist && fileExist.lenSvr > 1)

{

     fileSvr.nameSvr             = fileExist.nameSvr;

     fileSvr.pathSvr        = fileExist.pathSvr;

     fileSvr.perSvr              = fileExist.perSvr;

     fileSvr.lenSvr              = fileExist.lenSvr;

     fileSvr.complete       = fileExist.complete;

     db.Add(fileSvr);

    

     //触发事件

    up6_biz_event.file_create_same(fileSvr);

}//此文件不存在

else

{

     db.Add(fileSvr);

     //触发事件

    up6_biz_event.file_create(fileSvr);

    

     FileBlockWriter fr = new FileBlockWriter();

     fr.CreateFile(fileSvr.pathSvr,fileSvr.lenLoc);

}

接收文件块数据,在这个逻辑中我们接收文件块数据。控件对数据进行了优化,可以方便调试。如果用监控工具可以看到控件提交的数据。

boolean isMultipart = ServletFileUpload.isMultipartContent(request);

FileItemFactory factory = new DiskFileItemFactory();  

ServletFileUpload upload = new ServletFileUpload(factory);

List files = null;

try

{

     files = upload.parseRequest(request);

}

catch (FileUploadException e)

{// 解析文件数据错误 

    out.println("read file data error:" + e.toString());

    return;

  

}

 

FileItem rangeFile = null;

// 得到所有上传的文件

Iterator fileItr = files.iterator();

// 循环处理所有文件

while (fileItr.hasNext())

{

     // 得到当前文件

     rangeFile = (FileItem) fileItr.next();

     if(StringUtils.equals( rangeFile.getFieldName(),"pathSvr"))

     {

         pathSvr = rangeFile.getString();

         pathSvr = PathTool.url_decode(pathSvr);

     }

}

 

boolean verify = false;

String msg = "";

String md5Svr = "";

long blockSizeSvr = rangeFile.getSize();

if(!StringUtils.isBlank(blockMd5))

{

     md5Svr = Md5Tool.fileToMD5(rangeFile.getInputStream());

}

 

verify = Integer.parseInt(blockSize) == blockSizeSvr;

if(!verify)

{

     msg = "block size error sizeSvr:" + blockSizeSvr + "sizeLoc:" + blockSize;

}

 

if(verify && !StringUtils.isBlank(blockMd5))

{

     verify = md5Svr.equals(blockMd5);

     if(!verify) msg = "block md5 error";

}

 

if(verify)

{

     //保存文件块数据

     FileBlockWriter res = new FileBlockWriter();

     //仅第一块创建

     if( Integer.parseInt(blockIndex)==1) res.CreateFile(pathSvr,Long.parseLong(lenLoc));

     res.write( Long.parseLong(blockOffset),pathSvr,rangeFile);

     up6_biz_event.file_post_block(id,Integer.parseInt(blockIndex));

    

     JSONObject o = new JSONObject();

     o.put("msg", "ok");

     o.put("md5", md5Svr); 

     o.put("offset", blockOffset);//基于文件的块偏移位置

     msg = o.toString();

}

rangeFile.delete();

out.write(msg);

 

注:

1. 上面的java部分的代码可以直接使用,只需要将上传的图片路径及收集数据并将数据写入到数据库即可

2. 上面上传文件使用到了字节流,其实还可以使用别的流,这个需要读者自己在下面完善测试

3. BeanUtils是一个工具 便于将实体对应的属性赋给实体

4. 上传文件不能使用 request.getParameter("")获取参数了,而是直接将request解析,通过判断每一项是文件还是非文件,然后进行相应的操作(文件的话就是用流来读取,非文件的话,暂时保存到一个map中。)

后端代码逻辑大部分是相同的,目前能够支持MySQL,Oracle,SQL。在使用前需要配置一下数据库

效果展示:

​编辑

​编辑

​编辑

​编辑

 

视频演示:

 

windows控件安装,,linux-deb控件包安装,linux-rpm控件包安装,php7测试,php5测试,vue-cli-测试,asp.net-IIS测试,asp.net-阿里云(oss)测试,asp.net-华为云(obs)测试,jsp-springboot测试,ActiveX(x86)源码编译,ActiveX(x64)源码编译,Windows(npapi)源码编译,macOS源码编译,Linux(x86_64)源码编译,Linux(arm)源码编译,Linux(mips-uos)源码编译,Linux(mips-kylin-涉密环境)源码编译,sm4加密传输,压缩传输,

示例下载地址

源代码文档

asp.net源码下载jsp-springboot源码下载jsp-eclipse源码下载jsp-myeclipse源码下载php源码下载csharp-winform源码下载vue-cli源码下载c++源码下载

详细配置信息及思路


标签:function,文件,Java,端大,源码,分片,上传,id,fileSvr
From: https://www.cnblogs.com/songsu/p/17547313.html

相关文章

  • JAVA设计模式之适配器模式
    设计模式设计模式(DesignPattern)是前辈们对代码开发经验的总结,是解决特定问题的一系列套路。它不是语法规定,而是一套用来提高代码可复用性、可维护性、可读性、稳健性以及安全性的解决方案。总体来说设计模式分为三大类:创建型模式,共五种:工厂方法模式、抽象工厂模式、单例模式、......
  • 【面试必背知识】Java 中常见的异常有哪些?
    ......
  • 如何实现javav的具体操作步骤
    实现"javav"的步骤为了帮助刚入行的小白实现"javav",我们可以按照以下步骤进行操作:步骤描述步骤1创建一个名为"HelloWorld"的Java类步骤2在Java类中添加一个名为"main"的方法步骤3在main方法中输出"javav"下面我将为你详细解释每个步骤需要做什么,以及提供相......
  • JAVA SE基础《六》---- 方法
    目录一、方法定义、调用1、方法完整的定义形式、调用 2、方法的其他定义形式、调用二、方法使用的常见问题三、方法案例1、定义方法的技巧、计算1-n的和返回2、判断整数是奇数还是偶数3、数组求最值案例改方法实现四、方法调用的内存图五、方法参......
  • Java--next()方法和nextLine()方法的区别
    Java--next()方法和nextLine()方法的区别首先我们来看一下代码:importjava.util.Scanner;publicclassDemo01{publicstaticvoidmain(String[]args){Scannerscanner=newScanner(System.in);​System.out.println("请输入:");......
  • Java实现浏览器端大文件分片上传实例解析
    ​ 我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。首先我们需要了解的是上传文件三要素:1.表单提交方式:post(get方式提交有大小限制,post没有)2.表单的enctype属性:必须设置为multipart/form-data.3.表单必须......
  • 如何实现java技术栈的具体操作步骤
    Java技术栈实现指南概述在这篇文章中,我将向你介绍如何实现Java技术栈。Java技术栈是指一套开发工具和框架的集合,用于开发Java应用程序。我将为你提供一个简单的步骤表格,并详细解释每个步骤所需的代码。步骤表格步骤描述1.创建Java项目创建一个新的Java项目,可以使用E......
  • 解决java微服务的具体操作步骤
    实现Java微服务的流程为了帮助这位刚入行的小白开发者了解如何实现Java微服务,我将按照以下步骤详细介绍整个流程,并提供相应的代码示例。步骤一:定义服务接口和模型在开始实现Java微服务之前,首先需要定义服务接口和模型。服务接口定义了服务的功能和方法,而模型则定义了服务所使用......
  • 如何实现java卸载的具体操作步骤
    Java卸载Java是一种广泛使用的编程语言,但有时您可能需要卸载它。本文将向您介绍卸载Java的步骤,并提供相应的代码示例。卸载Java的步骤卸载Java的步骤因操作系统而异。下面将分别介绍Windows和Linux操作系统中卸载Java的方法。Windows操作系统以下是Windows操作系统中卸载Java......
  • 解决Java字节码的具体操作步骤
    如何实现Java字节码1.定义Java字节码是Java程序编译后生成的一种中间形式,它是一种与平台无关的二进制数据格式,可以在任何支持Java虚拟机(JVM)的平台上运行。通过Java字节码,我们可以将Java程序转化为一系列字节码指令,这些指令被JVM解释执行或者编译成机器码执行。2.实现步骤下面......