jsp web 大文件上传源代码

我们平时经常做的是上传文件,上传文件夹与上传文件类似,但也有一些不同之处,这次做了上传文件夹就记录下以备后用。

首先我们需要了解的是上传文件三要素:

1.表单提交方式:post (get方式提交有大小限制,post没有)

2.表单的enctype属性:必须设置为multipart/form-data.

3.表单必须有文件上传项:file,且文件项需要给定name值

上传文件夹需要增加一个属性webkitdirectory,像这样:

不过webkitdirectory属性有个问题,只能支持高版本的chrome,不能支持低版本的IE,如ie6,ie7,ie8,不能做到全浏览器适配,运行环境比较单一。

js中可以判断文件夹中文件数量及文件夹大小是否符合要求,不符合要求不能向后台提交:

前台HTML模板

this.GetHtmlFiles = function()

{

 var acx = "";

 acx += '

\

 

\

 

\

 

\

 

HttpUploader程序开发.pdf
\

 

(35%)
\

 

1000.23MB
\

 \

 

\

 

15.3MB 20KB/S 10:02:00
\

 \

 

\





 ';

 acx += '

';

 //文件夹模板

 acx += '

\

 

\

 

\

 

\

 

HttpUploader程序开发.pdf
\

 

(35%)
\

 

1000.23MB
\

 \

 

\

 

15.3MB 20KB/S 10:02:00
\

 \

 

\





 ';

 acx += '

';

 //上传列表

 acx += '

\

 

\

 选择多个文件\

 选择文件夹\

 粘贴文件和目录\

 安装控件\

 \

 

\

 

\

 \

 

 清除已完成文件\

 \

 ';

 return acx;

};

选择文件,选择文件夹,粘贴文件和文件夹的逻辑

this.open_files = function (json)

{

 for (var i = 0, l = json.files.length; i < l; ++i)

 {

  this.addFileLoc(json.files[i]);

 }

 setTimeout(function () { _this.PostFirst(); },500);

};

this.open_folders = function (json)

{

 for (var i = 0, l = json.folders.length; i < l; ++i) {

 this.addFolderLoc(json.folders[i]);

 }

 setTimeout(function () { _this.PostFirst(); }, 500);

};

this.paste_files = function (json)

{

 for (var i = 0, l = json.files.length; i < l; ++i)

 {

  this.addFileLoc(json.files[i]);

 }

};

后台在接收文件夹时不同之处在需要用MultipartHttpServletRequest

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);

 }

}


server端的包和类


jsp web 大文件上传源代码_第1张图片


文件块处页面,验证代码部分

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);


生成文件名称的逻辑

public String genFile(int uid, String md5,String nameLoc) throws IOException

{

 SimpleDateFormat fmtDD = new SimpleDateFormat("dd");

 SimpleDateFormat fmtMM = new SimpleDateFormat("MM");

 SimpleDateFormat fmtYY = new SimpleDateFormat("yyyy");


 Date date = new Date();

 String strDD = fmtDD.format(date);

 String strMM = fmtMM.format(date);

 String strYY = fmtYY.format(date);


 String path = this.getRoot() + "/";

 path = path.concat(strYY);

 path = path.concat("/");

 path = path.concat(strMM);

 path = path.concat("/");

 path = path.concat(strDD);

 path = path.concat("/");

 path = path.concat(md5);

 path = path.concat(".");

 path = path.concat(PathTool.getExtention(nameLoc));



 File fl = new File(path);


 return fl.getCanonicalPath();//

}


以下是service层做的处理:

整体模块划分如下:


jsp web 大文件上传源代码_第2张图片

其中数据类实体逻辑处理如下

public class FileInf {


 public FileInf(){}

 public String id="";

 public String pid="";

 public String pidRoot="";   

 /** * 表示当前项是否是一个文件夹项。 */

 public boolean fdTask=false;        

 // /// 是否是文件夹中的子文件 ///

 public boolean fdChild=false;

 /** * 用户ID。与第三方系统整合使用。 */

 public int uid=0;

 /** * 文件在本地电脑中的名称 */

 public String nameLoc="";

 /** * 文件在服务器中的名称。 */

 public String nameSvr="";

 /** * 文件在本地电脑中的完整路径。示例:D:\Soft\QQ2012.exe */

 public String pathLoc="";  

 /** * 文件在服务器中的完整路径。示例:F:\\ftp\\uer\\md5.exe */

 public String pathSvr="";

 /** * 文件在服务器中的相对路径。示例:/www/web/upload/md5.exe */

 public String pathRel="";

 /** * 文件MD5 */

 public String md5="";

 /** * 数字化的文件长度。以字节为单位,示例:120125 */

 public long lenLoc=0;

 /** * 格式化的文件尺寸。示例:10.03MB */

 public String sizeLoc="";

 /** * 文件续传位置。 */

 public long offset=0;

 /** * 已上传大小。以字节为单位 */

 public long lenSvr=0;

 /** * 已上传百分比。示例:10% */

 public String perSvr="0%";

 public boolean complete=false;

 public Date PostedTime = new Date();

 public boolean deleted=false;

 /** * 是否已经扫描完毕,提供给大型文件夹使用,大型文件夹上传完毕后开始扫描。 */

 public boolean scaned=false;

}

后台数据库中的逻辑基本上都用到了上面的实体类

文件数据表操作类如下

加载所有未完成的文件列表

public String GetAllUnComplete(int f_uid)

{

 StringBuilder sb = new StringBuilder();

 sb.append("select ");

 sb.append(" f_id");

 sb.append(",f_fdTask");    

 sb.append(",f_nameLoc");

 sb.append(",f_pathLoc");

 sb.append(",f_md5");

 sb.append(",f_lenLoc");

 sb.append(",f_sizeLoc");

 sb.append(",f_pos");

 sb.append(",f_lenSvr");

 sb.append(",f_perSvr");

 sb.append(",f_complete");

 sb.append(",f_pathSvr");//fix(2015-03-16):修复无法续传文件的问题。

 sb.append(" from up6_files ");//change(2015-03-18):联合查询文件夹数据

 sb.append(" where f_uid=? and f_deleted=0 and f_fdChild=0 and f_complete=0 and f_scan=0");//fix(2015-03-18):只加载未完成列表


 ArrayList files = new ArrayList();

 DbHelper db = new DbHelper();

 PreparedStatement cmd = db.GetCommand(sb.toString());

 try {

 cmd.setInt(1, f_uid);

 ResultSet r = db.ExecuteDataSet(cmd);

 while(r.next())

 {

 FileInf f  = new FileInf();

 f.uid = f_uid;

 f.id  = r.getString(1);

 f.fdTask  = r.getBoolean(2);              

 f.nameLoc  = r.getString(3);

 f.pathLoc  = r.getString(4);

 f.md5  = r.getString(5);

 f.lenLoc  = r.getLong(6);

 f.sizeLoc  = r.getString(7);

 f.offset  = r.getLong(8);

 f.lenSvr  = r.getLong(9);

 f.perSvr  = r.getString(10);

 f.complete  = r.getBoolean(11);

 f.pathSvr = r.getString(12);//fix(2015-03-19):修复无法续传文件的问题。

 files.add(f);


 }

 r.close();

 cmd.getConnection().close();

 cmd.close();

 } catch (SQLException e) {

 // TODO Auto-generated catch block

 e.printStackTrace();

 }


 if(files.size() < 1) return null;


 Gson g = new Gson();

 return g.toJson( files);//bug:arrFiles为空时,此行代码有异常

}

实现后的整体效果如下


jsp web 大文件上传源代码_第3张图片

文件夹上传完后的效果


jsp web 大文件上传源代码_第4张图片

服务器保存的文件夹数据,而且层级结构与本地客户端是一致的。这在OA系统中,或者网盘系统中使用时是非常有用的


jsp web 大文件上传源代码_第5张图片

后端代码逻辑大部分是相同的,目前能够支持MySQL,Oracle,SQL。在使用前需要配置一下数据库,详细信息可以网上搜索“up6大文件上传控件”

你可能感兴趣的:(jsp web 大文件上传源代码)