在servlet2.5中,我们实现文件上传功能,一般都会去借助第三方的插件,但在servlet 3.0 中提供了对文件上传的支持,我们再也无需去导入第三方的插件,就能够调用servlet 3.0 自身的api 实现文件上传功能。
文件上传可以分为同步上传和异步上传,当然网上还有一些关于上传的插件可供使用,这里我分别讲述下。
同步实现上传
同步上传效果图jsp界面代码:
<form action="${pageContext.request.contextPath}/UploadServlet"
method="post" enctype="multipart/form-data">
上传文件:
<input type="file" name="file" id="file" accept=".jpg" multiple>
<br>
<input type="submit" value="上传">
</form>
我们前端使用 type="file"标签进行二进制文件传输,在后台使用注解@MultipartConfig 标记servlet解析文件读取part。
这是在servlet 3.0以后才能支持哦
@MultipartConfig(maxFileSize=1024*1024*5)//标识Servlet支持文件上传,设置约束,最大上传5M
当我们上传文件的时候,需要考虑给文件重命名,以及以日为单位建立个文件夹进行图片的存储。
首先,建立文件夹(两个,一个总的存储文件夹,一个存储一天的文件夹)
public void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//存储路径物理路径
String savePath = request.getServletContext().getRealPath("/uploadFile");
//得到当前日期,每天一个以日期命名文件夹,方便管理
String crtdate = DateUtils.format(new Date(), "yyyyMMdd");
String dirc = savePath+File.separator+crtdate;
// 创建目录
File uploadDir = new File(dirc);
if (uploadDir.getParentFile() != null || !uploadDir.getParentFile().isDirectory()) {
//创建目录6
uploadDir.getParentFile().mkdirs();
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
}
接下来是将jsp传递过来的文件上传到指定路径,采用Part进行上传,期间当然需要对 文件进行改名字。
//获取上传的文件集合
Collection<Part> parts = request.getParts();
//上传单个文件
if (parts.size()==1) {
//Servlet3.0将multipart/form-data的POST请求封装成Part,通过Part对上传的文件进行操作。
//Part part = parts[0];//从上传的文件集合中获取Part对象
Part part = request.getPart("file");//通过表单file控件(<input type="file" name="file">)的名字直接获取Part对象
//Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来
//获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String header = part.getHeader("content-disposition");
//获取文件名aaa.aa.bb.jpg
String fileName = getNewName(getFileName(header));
String imgurl = dirc+File.separator+fileName;
//把文件写到指定路径
part.write(imgurl);
}else {
//一次性上传多个文件
for (Part part : parts) {//循环处理上传的文件
//获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String header = part.getHeader("content-disposition");
//获取文件名
String fileName = getNewName(getFileName(header));
//把文件写到指定路径
part.write(savePath+File.separator+fileName);
}
}
PrintWriter out = response.getWriter();
out.println("上传成功");
out.flush();
out.close();
因为需要对文件进行重命名,所以需要获取到文件名,好截取文件的格式,Servlet3没有提供直接获取文件名的方法,需要从请求头中解析出来。
String header = part.getHeader("content-disposition");
/**
* 根据请求头解析出文件名
* 请求头的格式:火狐和google浏览器下:form-data; name="file"; filename="snmp4j--api.zip"
* IE浏览器下:form-data; name="file"; filename="E:\snmp4j--api.zip"
* @param header 请求头
* @return 文件名
*/
public String getFileName(String header) {
/**
* String[] tempArr1 = header.split(";");代码执行完之后,在不同的浏览器下,tempArr1数组里面的内容稍有区别
* 火狐或者google浏览器下:tempArr1={form-data,name="file",filename="snmp4j--api.zip"}
* IE浏览器下:tempArr1={form-data,name="file",filename="E:\snmp4j--api.zip"}
*/
String[] tempArr1 = header.split(";");
/**
*火狐或者google浏览器下:tempArr2={filename,"snmp4j--api.zip"}
*IE浏览器下:tempArr2={filename,"E:\snmp4j--api.zip"}
*/
String[] tempArr2 = tempArr1[2].split("=");
//获取文件名,兼容各种浏览器的写法
String fileName = tempArr2[1].substring(tempArr2[1].lastIndexOf("\\")+1).replaceAll("\"", "");
return fileName;
}
获取到文件名之后,就可以自己截取后缀名然后与时间System.currentTimeMillis()进行拼接,则可以得到一个随机唯一的数字,如果考虑高并发的情况下,要确保唯一,可以在名字里在加上一位随机数。
到目前,就实现了同步的文件上传功能。
formdata异步实现文件上传
首先看下jsp界面:
<form id= "uploadForm">
<p >图片作者: <input type="text" name="filename" value= ""/></p >
<p >图片描述: <input type="text" name="filesay" value= ""/></p >
<p >上传文件: <input type="file" name="file"/></ p>
<input type="button" value="上传" onclick="doUpload()" />
</form>
<script type="text/javascript">
function doUpload(){
//封装FormData(dom对象)
var deptForm = $("#uploadForm")[0];
var formdata = new FormData(deptForm);
$.ajax({
url:"${pageContext.request.contextPath}/AjaxUploadServlet",
type:"post",
data: formdata,
//dataType:"json",
contentType: false, //3.必须false才会避开jQuery对 formdata 的默认处理, XMLHttpRequest会对 formdata 进行正确的处理
processData: false, //4.必须false才会自动加上正确的Content-Type
success:function(data){
console.info(data);
//location.href = "sss.servlet";//同步跳转
},
error:function(){
alert("出错了!");
}
});
}
</script>
需要注意的是,使用var formdata=new FormData(Dom元素); 传递的是一个Dom元素而不是一个JQ对象。
使用formdata时,需要在servlet加上注解的支持。不然servlet通过request是获取不到值的
@MultipartConfig(maxFileSize=1024*1024*8)
创建文件夹,主文件夹(uploadFile)包含所有上传文件
以日为单位创建日文件夹,存放当日上传文件。
定义一个bean,将前台界面传过来的参数以及上传图片的路径存储在bean里面,传递给dao层,进行数据库存储,实现持久化。
request.setCharacterEncoding("utf-8");
response.setCharacterEncoding("utf-8");
response.setContentType("text/html;charset=utf-8");
//存储路径物理路径
String savePath = request.getServletContext().getRealPath("/uploadFile");
//得到当前日期,每天一个以日期命名文件夹,方便管理
String crtdate = DateUtils.format(new Date(), "yyyyMMdd");
String dirc = savePath+File.separator+crtdate;
// 创建目录
File uploadDir = new File(dirc);
if (uploadDir.getParentFile() != null || !uploadDir.getParentFile().isDirectory()) {
//创建目录6
uploadDir.getParentFile().mkdirs();
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
}
String filename=request.getParameter("filename");
String filesay=request.getParameter("filesay");
PicModel picModel=new PicModel();
picModel.setFilename(filename);
picModel.setFilesay(filesay);
String imgs="";
//获取上传的文件集合
Collection<Part> parts = request.getParts();
for (Part part : parts) {
//获取请求头,请求头的格式:form-data; name="file"; filename="snmp4j--api.zip"
String header = part.getHeader("content-disposition");
//获取文件名
String fileName = getNewName(getFileName(header));
//把文件写到指定路径
if(!"".equals(fileName)){
//20170914/15465456564564.jgp
part.write(dirc+File.separator+fileName);
imgs += ","+crtdate+File.separator+fileName;
}
}
if(imgs.length()!=0)
{
imgs = imgs.substring(1);
}
picModel.setImgurls(imgs);
//调用servie方法,插入数据库
PrintWriter out = response.getWriter();
out.println("上传成功");
out.flush();
out.close();
网友评论