Java与WebUploader相结合实现文件上传功能(实例代码)
程序员文章站
2024-03-02 14:49:52
之前自己写小项目的时候也碰到过文件上传的问题,没有找到很好的解决方案。虽然之前网找各种解决方案的时候也看到过webuploader,但没有进一步深究。这次稍微深入了解了些,...
之前自己写小项目的时候也碰到过文件上传的问题,没有找到很好的解决方案。虽然之前网找各种解决方案的时候也看到过webuploader,但没有进一步深究。这次稍微深入了解了些,这里也做个小结。
简单的文件和普通数据上传并保存
jsp页面:
<%@ page language="java" contenttype="text/html; charset=utf-8" pageencoding="utf-8"%> <!doctype html public "-//w3c//dtd html 4.01 transitional//en" "http://www.w3.org/tr/html4/loose.dtd"> <html> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8"> <title>insert title here</title> </head> <body> <form action="${pagecontext.request.contextpath }/fileuploadservlet" method="post" enctype="multipart/form-data"> 文件:<input type="file" value="请选择文件" name="file" /> <br/> 信息:<input type="text" name="info" /> <br/> <input type="submit" value="提交" /> </form> </body> </html>
servlet:
package com.yihengliu.web.action; import java.io.file; import java.io.ioexception; import java.io.inputstream; import java.util.list; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; import org.apache.commons.fileupload.fileitem; import org.apache.commons.fileupload.disk.diskfileitemfactory; import org.apache.commons.fileupload.servlet.servletfileupload; import org.apache.commons.io.fileutils; /** * servlet user to accept file upload */ public class fileuploadservlet extends httpservlet { private static final long serialversionuid = 1l; private string serverpath = "e:/"; protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { response.getwriter().append("served at: ").append(request.getcontextpath()); system.out.println("进入后台..."); // 1.创建diskfileitemfactory对象,配置缓存用 diskfileitemfactory diskfileitemfactory = new diskfileitemfactory(); // 2. 创建 servletfileupload对象 servletfileupload servletfileupload = new servletfileupload(diskfileitemfactory); // 3. 设置文件名称编码 servletfileupload.setheaderencoding("utf-8"); // 4. 开始解析文件 try { list<fileitem> items = servletfileupload.parserequest(request); for (fileitem fileitem : items) { if (fileitem.isformfield()) { // >> 普通数据 string info = fileitem.getstring("utf-8"); system.out.println("info:" + info); } else { // >> 文件 // 1. 获取文件名称 string name = fileitem.getname(); // 2. 获取文件的实际内容 inputstream is = fileitem.getinputstream(); // 3. 保存文件 fileutils.copyinputstreamtofile(is, new file(serverpath + "/" + name)); } } } catch (exception e) { e.printstacktrace(); } } protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { doget(request, response); } }
使用webuploader组件上传
分片、并发,预览、压缩,多途径添加文件夹(文件多选,拖拽等),妙传
页面样式使用
<html> <title>使用webuploader上传</title> <!-- 1.引入文件 --> <link rel="stylesheet" type="text/css" href="${pagecontext.request.contextpath }/js/webuploader.css" rel="external nofollow" > <script type="text/javascript" src="${pagecontext.request.contextpath }/js/jquery-2.1.4.min.js"></script> <script type="text/javascript" src="${pagecontext.request.contextpath }/js/webuploader.js"></script> </head> <body> <!-- 2.创建页面元素 --> <div id="upload"> <div id="filepicker">文件上传</div> </div> <!-- 3.添加js代码 --> <script type="text/javascript"> var uploader = webuploader.create( { swf:"${pagecontext.request.contextpath }/js/uploader.swf", server:"${pagecontext.request.contextpath }/fileuploadservlet", pick:"#filepicker", auto:true } ); </script> </body> </html>
- 生成文件名列表、实时显示上传进度、显示缩略图
- 增加文件列表div,
<div id="filelist"></div>
- 生成缩略图和显示上传进度
// 生成缩略图和上传进度 uploader.on("filequeued", function(file) { // 把文件信息追加到filelist的div中 $("#filelist").append("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='percentage'><span></div></div>") // 制作缩略图 // error:不是图片,则有error // src:代表生成缩略图的地址 uploader.makethumb(file, function(error, src) { if (error) { $("#" + file.id).find("img").replacewith("<span>无法预览 </span>"); } else { $("#" + file.id).find("img").attr("src", src); } }); } ); // 监控上传进度 // percentage:代表上传文件的百分比 uploader.on("uploadprogress", function(file, percentage) { $("#" + file.id).find("span.percentage").text(math.round(percentage * 100) + "%"); });
- 拖拽上传、粘贴上传
- 创建拖拽区域并设置样式:
<style type="text/css"> #dndarea { width: 200px; height: 100px; border-color: red; border-style: dashed; } </style> <!-- 创建用于拖拽的区域 --> <div id="dndarea"></div>
- 基本配置中增加dnd区域配置(开启拖拽)
屏蔽拖拽区域外的响应
开启粘贴功能
var uploader = webuploader.create( { swf:"${pagecontext.request.contextpath }/js/uploader.swf", server:"${pagecontext.request.contextpath }/fileuploadservlet", pick:"#filepicker", auto:true, // 开启拖拽 dnd:"#dndarea", // 屏蔽拖拽区域外的响应 disableglobaldnd:true, // } );
- 文件的分块上传
前端根据需要发送的文件生成一个md5字符串发送给后台,后台创建以该md5字符串命名的文件夹。前端分块发送文件并发送文件块序号给后台,后台接收到文件后按序号名称保存。前端发送完成后通知后台合并文件。
- 前端配置,开启是否分块、分块大小、线程个数等
// 上传基本配置 var uploader = webuploader.create( { swf:"${pagecontext.request.contextpath }/js/uploader.swf", server:"${pagecontext.request.contextpath }/fileuploadservlet", pick:"#filepicker", auto:true, dnd:"#dndarea", disableglobaldnd:true, paste:"#uploader", // 分块上传设置 // 是否分块 chunked:true, // 每块文件大小(默认5m) chunksize:5*1024*1024, // 开启几个并非线程(默认3个) threads:3, // 在上传当前文件时,准备好下一个文件 preparenextfile:true } );
- 前端监听分块
可以分为三个时间点:
- before-send-file: 该方法在文件上传前调用(只会在一个文件上传前调用)。
可以在该方法中获取文件的md5字符串作为后台保存分块文件的目录名
- before-send: 该方法在每个分块文件上传前调用(每个分块上传前都会调用)。
可以在该方法中发送md5字符串到后台,后台判断是否已经存在分块决定是否发送以达到断点续传的功能
- after-send-file: 该方法在所有文件上传完成没有错误之后调用(所有分块上传完成后调用)。
可以在该方法中通知后台合并所有分块
- 前端获取文件md5字符串,发送每个分块时发送到后台,后台接收如果不存在文件夹创建文件夹,保存分块发送的文件
// 监听分块上传的时间点,断点续传 var filemd5; webuploader.uploader.register({ "before-send-file":"beforesendfile", "before-send":"beforesend", "after-send-file":"aftersendfile" },{ beforesendfile:function(file) { // 创建一个deffered,用于通知是否完成操作 var deferred = webuploader.deferred(); // 计算文件的唯一标识,用于断点续传和妙传 (new webuploader.uploader()).md5file(file, 0, 5*1024*1024) .progress(function(percentage){ $("#"+file.id).find("span.state").text("正在获取文件信息..."); }) .then(function(val) { filemd5 = val; $("#" + file.id).find("span.state").text("成功获取文件信息"); // 放行 deferred.resolve(); }); // 通知完成操作 return deferred.promise(); }, beforesend:function() { var deferred = webuploader.deferred(); // 发送文件md5字符串到后台 this.owner.options.formdata.filemd5 = filemd5; deferred.resolve(); return deferred.promise(); }, aftersendfile:function() { } } );
添加state标签
$("#filelist").append("<div id='" + file.id + "'><img/><span>" + file.name + "</span><div><span class='state'></span></div><div><span class='percentage'></span></div></div>");
保存文件
// 4. 开始解析文件 // 文件md5获取的字符串 string filemd5 = null; // 文件的索引 string chunk = null; try { list<fileitem> items = servletfileupload.parserequest(request); for (fileitem fileitem : items) { if (fileitem.isformfield()) { // >> 普通数据 string fieldname = fileitem.getfieldname(); if ("info".equals(fieldname)) { string info = fileitem.getstring("utf-8"); system.out.println("info:" + info); } if ("filemd5".equals(fieldname)) { filemd5 = fileitem.getstring("utf-8"); system.out.println("filemd5:" + filemd5); } if ("chunk".equals(fieldname)) { chunk = fileitem.getstring("utf-8"); system.out.println("chunk:" + chunk); } } else { // >> 文件 /*// 1. 获取文件名称 string name = fileitem.getname(); // 2. 获取文件的实际内容 inputstream is = fileitem.getinputstream(); // 3. 保存文件 fileutils.copyinputstreamtofile(is, new file(serverpath + "/" + name));*/ // 如果文件夹没有创建文件夹 file file = new file(serverpath + "/" + filemd5); if (!file.exists()) { file.mkdirs(); } // 保存文件 file chunkfile = new file(serverpath + "/" + filemd5 + "/" + chunk); fileutils.copyinputstreamtofile(fileitem.getinputstream(), chunkfile); } }
- 前端通知action进行合并文件
前端增加:
// 通知合并分块 $.ajax( { type:"post", url:"${pagecontext.request.contextpath}/uploadactionservlet?action=mergechunks", data:{ filemd5:filemd5 }, success:function(response){ } } );
新增合并action:
package com.yihengliu.web.action; import java.io.file; import java.io.filefilter; import java.io.fileinputstream; import java.io.fileoutputstream; import java.io.ioexception; import java.nio.channels.filechannel; import java.util.arraylist; import java.util.arrays; import java.util.collections; import java.util.comparator; import java.util.list; import java.util.uuid; import javax.servlet.servletexception; import javax.servlet.http.httpservlet; import javax.servlet.http.httpservletrequest; import javax.servlet.http.httpservletresponse; /** * 合并上传文件 */ public class uploadactionservlet extends httpservlet { private static final long serialversionuid = 1l; private string serverpath = "e:/"; protected void doget(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { system.out.println("进入合并后台..."); string action = request.getparameter("action"); if ("mergechunks".equals(action)) { // 获得需要合并的目录 string filemd5 = request.getparameter("filemd5"); // 读取目录所有文件 file f = new file(serverpath + "/" + filemd5); file[] filearray = f.listfiles(new filefilter() { // 排除目录,只要文件 @override public boolean accept(file pathname) { 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) { if (integer.parseint(o1.getname()) < integer.parseint(o2.getname())) { return -1; } return 1; } }); // 新建保存文件 file outputfile = new file(serverpath + "/" + uuid.randomuuid().tostring() + ".zip"); // 创建文件 outputfile.createnewfile(); // 输出流 fileoutputstream fileoutputstream = new fileoutputstream(outputfile); filechannel outchannel = fileoutputstream.getchannel(); // 合并 filechannel inchannel; for (file file : filelist) { inchannel = new fileinputstream(file).getchannel(); inchannel.transferto(0, inchannel.size(), outchannel); inchannel.close(); // 删除分片 file.delete(); } // 关闭流 fileoutputstream.close(); outchannel.close(); // 清除文件加 file tempfile = new file(serverpath + "/" + filemd5); if (tempfile.isdirectory() && tempfile.exists()) { tempfile.delete(); } system.out.println("合并文件成功"); } } protected void dopost(httpservletrequest request, httpservletresponse response) throws servletexception, ioexception { doget(request, response); } }
- 断点续传
前端页面发送前添加校验,校验是否已经上传分块
beforesend:function(block) { var deferred = webuploader.deferred(); // 支持断点续传,发送到后台判断是否已经上传过 $.ajax( { type:"post", url:"${pagecontext.request.contextpath}/uploadactionservlet?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(); } } } ); // 发送文件md5字符串到后台 this.owner.options.formdata.filemd5 = filemd5; return deferred.promise(); }
- action中添加校验
else if ("checkchunk".equals(action)) { // 校验文件是否已经上传并返回结果给前端 // 文件唯一表示 string filemd5 = request.getparameter("filemd5"); // 当前分块下标 string chunk = request.getparameter("chunk"); // 当前分块大小 string chunksize = request.getparameter("chunksize"); // 找到分块文件 file checkfile = new file(serverpath + "/" + 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}"); } }
以上所述是小编给大家介绍的java与webuploader相结合实现文件上传功能(实例代码),希望对大家有所帮助
推荐阅读
-
Java与WebUploader相结合实现文件上传功能(实例代码)
-
java实现图片的上传与展示实例代码
-
java中struts2实现文件上传下载功能实例解析
-
webuploader在springMVC+jquery+Java开发环境下的大文件分片上传的实例代码
-
webuploader 实现图片批量上传功能附实例代码
-
Java中使用fileupload组件实现文件上传功能的实例代码
-
java文件操作代码片断实例实现统计文件中字母出现的个数功能
-
FasfDFS整合Java实现文件上传下载功能实例详解
-
Java中使用fileupload组件实现文件上传功能的实例代码
-
java文件操作代码片断实例实现统计文件中字母出现的个数功能