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。在使用前需要配置一下数据库,可以参考我写的这篇文章:http://blog.ncmem.com/wordpress/2019/08/12/java-http%E5%A4%A7%E6%96%87%E4%BB%B6%E6%96%AD%E7%82%B9%E7%BB%AD%E4%BC%A0%E4%B8%8A%E4%BC%A0/

Java多级文件夹上传的更多相关文章

  1. java+http文件夹上传

    在web项目中上传文件夹现在已经成为了一个主流的需求.在OA,或者企业ERP系统中都有类似的需求.上传文件夹并且保留层级结构能够对用户行成很好的引导,用户使用起来也更方便.能够提供更高级的应用支撑. ...

  2. java实现文件夹上传

    文件上传下载,与传统的方式不同,这里能够上传和下载10G以上的文件.而且支持断点续传. 通常情况下,我们在网站上面下载的时候都是单个文件下载,但是在实际的业务场景中,我们经常会遇到客户需要批量下载的场 ...

  3. Java Web 项目的文件/文件夹上传下载

    需求: 支持大文件批量上传(20G)和下载,同时需要保证上传期间用户电脑不出现卡死等体验: 内网百兆网络上传速度为12MB/S 服务器内存占用低 支持文件夹上传,文件夹中的文件数量达到1万个以上,且包 ...

  4. java web 实现文件夹上传(保留目录结构)

    今天我弄了一下文件夹上传(很简单的 首先,我们的html需要这样写 <form action="/file/upload" enctype="multipart/f ...

  5. java文件夹上传下载组件

    核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...

  6. 文件夹上传插件webupload插件

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 先说下要求: PC端全平台支持,要求支持Windows,Mac,Linux 支持所 ...

  7. 文件夹上传控件webupload插件

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...

  8. Web 项目的文件/文件夹上传下载

    我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用. 这次项目的需求: 支持大文件的上传和续传,要求续传支持所有浏览器,包括ie6,ie7,i ...

  9. webuploader+文件夹上传

    在Web应用系统开发中,文件上传和下载功能是非常常用的功能,今天来讲一下JavaWeb中的文件上传和下载功能的实现. 先说下要求: PC端全平台支持,要求支持Windows,Mac,Linux 支持所 ...

随机推荐

  1. [Python3] 026 常用模块 calendar

    目录 calendar 1. calendar.calendar(year, w, l, c, m) 2. calendar.prcal(year, w, l, c, m) 3. calendar.m ...

  2. spring boot-6.profile 多环境支持

    在正式项目中一般都会区分多个环境,一般至少分为开发环境,测试生产环境,生产环境,实际可能会有更加精细的区分,针对不同的环境,项目的配置可能需要切换,spring boot 提供了很方便的环境切换方式. ...

  3. spring boot1.1 idea + springboot + mybatis(mybatis-generator) +mysql +html实现简单的登录注册

    前言 这两年springboot比较火,而我平时的工作中不怎么使用spring boot,所以工作之余就自己写写项目练练手,也跟大家一起学习. 打算从最开始的搭架子,登录注册,到后台管理的增删改查,业 ...

  4. mysql 官网下载太慢了,来这里!!!

    RT.去官网下载mysql简直是折磨,太慢了!!! 但我还是坚持住了,下载下来了,我自己下载的是 MAC 5.7.27版本,网盘分享下,有需要的自提吧: 链接:https://pan.baidu.co ...

  5. redis内存满了怎么办?

    redis最为缓存数据库,一般用于存储缓存数据,用于缓解数据库压力,但是缓存太多,内存满了怎么办呢.一般有以下几种方法 一.增加内存 redis存储于内存中,数据太多,占用太多内存,那么增加内存就是最 ...

  6. 初步学习jquery学习笔记(五)

    jquery学习笔记五 jquery遍历 什么是遍历? 从某个标签开始,按照某种规则移动,直到找到目标标签为止 标签树 <div> <ul> <li> <sp ...

  7. HTTP、HTTPS 了解一下

    什么是HTTP? 超文本传输协议,是一个基于请求与响应,无状态的,应用层的协议,常基于TCP/IP协议传输数据,互联网上应用最为广泛的一种网络协议,所有的WWW文件都必须遵守这个标准.设计HTTP的初 ...

  8. 如何在一个线程环境中使用一个线程非安全的java类

    在开发过程中 当我们拿到一个线程非安全的java类的时候,我们可以额外创建这个类的管理类 并在管理类中控制同步 比如 一个非线程安全的Pair类 package test.thread.sx.test ...

  9. localStorage 理解

    localStorage对象是HTML5的客户端存储持久化数据的方案.为了能访问到同一个localStorage对象,页面必须来自同一个域名(子域名无效),使用同一种协议,在同一个端口上. 过期策略: ...

  10. 我所不知的JS

    几天前在阅读 MDN 文档时我发现了一些我从来不知道的 JS 特性和 API. 下面是一份简短的清单, 无论有用不有用——学习 JS 的道路似乎是没有尽头的. 标签语句 在 JS 中,你可以对 for ...