标签:
创建一个FileUploadAndDownLoad项目,加入Apache的commons-fileupload文件上传组件的相关Jar包,如下图所示:
upload.jsp页面的代码如下:
1<%@ page language="java" pageEncoding="UTF-8"%> 2<!DOCTYPE HTML> 3<html> 4<head> 5<title>文件上传</title> 6</head> 7 8<body> 9<form action="${pageContext.request.contextPath}/servlet/UploadHandleServlet" enctype="multipart/form-data" method="post">10 上传用户:<input type="text" name="username"><br/>11 上传文件1:<input type="file" name="file1"><br/>12 上传文件2:<input type="file" name="file2"><br/>13<input type="submit" value="提交">14</form>15</body>16</html>
message.jsp的代码如下:
1<%@ page language="java" pageEncoding="UTF-8"%> 2<!DOCTYPE HTML> 3<html> 4<head> 5<title>消息提示</title> 6</head> 7 8<body> 9 ${message} 10</body>11</html>
UploadHandleServlet的代码如下:
1package me.gacl.web.controller; 2 3import java.io.File; 4import java.io.FileOutputStream; 5import java.io.IOException; 6import java.io.InputStream; 7import java.util.List; 8import javax.servlet.ServletException; 9import javax.servlet.http.HttpServlet; 10import javax.servlet.http.HttpServletRequest; 11import javax.servlet.http.HttpServletResponse; 12import org.apache.commons.fileupload.FileItem; 13import org.apache.commons.fileupload.disk.DiskFileItemFactory; 14import org.apache.commons.fileupload.servlet.ServletFileUpload; 15 16publicclass UploadHandleServlet extends HttpServlet { 17 18public void doGet(HttpServletRequest request, HttpServletResponse response) 19throws ServletException, IOException { 20//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 21 String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); 22 File file = new File(savePath); 23//判断上传文件的保存目录是否存在 24if (!file.exists() && !file.isDirectory()) { 25 System.out.println(savePath+"目录不存在,需要创建"); 26//创建目录 27 file.mkdir(); 28 } 29//消息提示 30 String message = ""; 31try{ 32//使用Apache文件上传组件处理文件上传步骤: 33//1、创建一个DiskFileItemFactory工厂 34 DiskFileItemFactory factory = new DiskFileItemFactory(); 35//2、创建一个文件上传解析器 36 ServletFileUpload upload = new ServletFileUpload(factory); 37//解决上传文件名的中文乱码 38 upload.setHeaderEncoding("UTF-8"); 39//3、判断提交上来的数据是否是上传表单的数据 40if(!ServletFileUpload.isMultipartContent(request)){ 41//按照传统方式获取数据 42return; 43 } 44//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 45 List<FileItem> list = upload.parseRequest(request); 46for(FileItem item : list){ 47//如果fileitem中封装的是普通输入项的数据 48if(item.isFormField()){ 49 String name = item.getFieldName(); 50//解决普通输入项的数据的中文乱码问题 51 String value = item.getString("UTF-8"); 52//value = new String(value.getBytes("iso8859-1"),"UTF-8"); 53 System.out.println(name + "=" + value); 54 }else{//如果fileitem中封装的是上传文件 55//得到上传的文件名称, 56 String filename = item.getName(); 57 System.out.println(filename); 58if(filename==null || filename.trim().equals("")){ 59continue; 60 } 61//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 62//处理获取到的上传文件的文件名的路径部分,只保留文件名部分 63 filename = filename.substring(filename.lastIndexOf("\\")+1); 64//获取item中的上传文件的输入流 65 InputStream in = item.getInputStream(); 66//创建一个文件输出流 67 FileOutputStream out = new FileOutputStream(savePath + "\\" + filename); 68//创建一个缓冲区 69byte buffer[] = newbyte[1024]; 70//判断输入流中的数据是否已经读完的标识 71int len = 0; 72//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据 73while((len=in.read(buffer))>0){ 74//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中 75 out.write(buffer, 0, len); 76 } 77//关闭输入流 78 in.close(); 79//关闭输出流 80 out.close(); 81//删除处理文件上传时生成的临时文件 82 item.delete(); 83 message = "文件上传成功!"; 84 } 85 } 86 }catch (Exception e) { 87 message= "文件上传失败!"; 88 e.printStackTrace(); 89 90 } 91 request.setAttribute("message",message); 92 request.getRequestDispatcher("/message.jsp").forward(request, response); 93 } 94 95publicvoid doPost(HttpServletRequest request, HttpServletResponse response) 96throws ServletException, IOException { 97 98 doGet(request, response); 99 } 100 }
在Web.xml文件中注册UploadHandleServlet
1<servlet>2<servlet-name>UploadHandleServlet</servlet-name>3<servlet-class>me.gacl.web.controller.UploadHandleServlet</servlet-class>4</servlet>56<servlet-mapping>7<servlet-name>UploadHandleServlet</servlet-name>8<url-pattern>/servlet/UploadHandleServlet</url-pattern>9</servlet-mapping>
运行效果如下:
文件上传成功之后,上传的文件保存在了WEB-INF目录下的upload目录,如下图所示:
上述的代码虽然可以成功将文件上传到服务器上面的指定目录当中,但是文件上传功能有许多需要注意的小细节问题,以下列出的几点需要特别注意的
1、为保证服务器安全,上传文件应该放在外界无法直接访问的目录下,比如放于WEB-INF目录下。
2、为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名。
3、为防止一个目录下面出现太多文件,要使用hash算法打散存储。
4、要限制上传文件的最大值。
5、要限制上传文件的类型,在收到上传文件名时,判断后缀名是否合法。
针对上述提出的5点细节问题,我们来改进一下UploadHandleServlet,改进后的代码如下:
1package me.gacl.web.controller; 2 3import java.io.File; 4import java.io.FileOutputStream; 5import java.io.IOException; 6import java.io.InputStream; 7import java.util.List; 8import java.util.UUID; 9 10import javax.servlet.ServletException; 11import javax.servlet.http.HttpServlet; 12import javax.servlet.http.HttpServletRequest; 13import javax.servlet.http.HttpServletResponse; 14import org.apache.commons.fileupload.FileItem; 15import org.apache.commons.fileupload.FileUploadBase; 16import org.apache.commons.fileupload.ProgressListener; 17import org.apache.commons.fileupload.disk.DiskFileItemFactory; 18import org.apache.commons.fileupload.servlet.ServletFileUpload; 19 20/** 21* @ClassName: UploadHandleServlet 22* @Description: TODO(这里用一句话描述这个类的作用) 23* @author: 孤傲苍狼 24* @date: 2015-1-3 下午11:35:50 25* 26*/ 27publicclass UploadHandleServlet extends HttpServlet { 28 29publicvoid doGet(HttpServletRequest request, HttpServletResponse response) 30throws ServletException, IOException { 31//得到上传文件的保存目录,将上传的文件存放于WEB-INF目录下,不允许外界直接访问,保证上传文件的安全 32 String savePath = this.getServletContext().getRealPath("/WEB-INF/upload"); 33//上传时生成的临时文件保存目录 34 String tempPath = this.getServletContext().getRealPath("/WEB-INF/temp"); 35 File tmpFile = new File(tempPath); 36if (!tmpFile.exists()) { 37//创建临时目录 38 tmpFile.mkdir(); 39 } 40 41//消息提示 42 String message = ""; 43try{ 44//使用Apache文件上传组件处理文件上传步骤: 45//1、创建一个DiskFileItemFactory工厂 46 DiskFileItemFactory factory = new DiskFileItemFactory(); 47//设置工厂的缓冲区的大小,当上传的文件大小超过缓冲区的大小时,就会生成一个临时文件存放到指定的临时目录当中。 48 factory.setSizeThreshold(1024*100);//设置缓冲区的大小为100KB,如果不指定,那么缓冲区的大小默认是10KB 49//设置上传时生成的临时文件的保存目录 50 factory.setRepository(tmpFile); 51//2、创建一个文件上传解析器 52 ServletFileUpload upload = new ServletFileUpload(factory); 53//监听文件上传进度 54 upload.setProgressListener(new ProgressListener(){ 55publicvoid update(long pBytesRead, long pContentLength, int arg2) { 56 System.out.println("文件大小为:" + pContentLength + ",当前已处理:" + pBytesRead); 57/** 58 * 文件大小为:14608,当前已处理:4096 59 文件大小为:14608,当前已处理:7367 60 文件大小为:14608,当前已处理:11419 61 文件大小为:14608,当前已处理:14608 62*/ 63 } 64 }); 65//解决上传文件名的中文乱码 66 upload.setHeaderEncoding("UTF-8"); 67//3、判断提交上来的数据是否是上传表单的数据 68if(!ServletFileUpload.isMultipartContent(request)){ 69//按照传统方式获取数据 70return; 71 } 72 73//设置上传单个文件的大小的最大值,目前是设置为1024*1024字节,也就是1MB 74 upload.setFileSizeMax(1024*1024); 75//设置上传文件总量的最大值,最大值=同时上传的多个文件的大小的最大值的和,目前设置为10MB 76 upload.setSizeMax(1024*1024*10); 77//4、使用ServletFileUpload解析器解析上传数据,解析结果返回的是一个List<FileItem>集合,每一个FileItem对应一个Form表单的输入项 78 List<FileItem> list = upload.parseRequest(request); 79for(FileItem item : list){ 80//如果fileitem中封装的是普通输入项的数据 81if(item.isFormField()){ 82 String name = item.getFieldName(); 83//解决普通输入项的数据的中文乱码问题 84 String value = item.getString("UTF-8"); 85//value = new String(value.getBytes("iso8859-1"),"UTF-8"); 86 System.out.println(name + "=" + value); 87 }else{//如果fileitem中封装的是上传文件 88//得到上传的文件名称, 89 String filename = item.getName(); 90 System.out.println(filename); 91if(filename==null || filename.trim().equals("")){ 92continue; 93 } 94//注意:不同的浏览器提交的文件名是不一样的,有些浏览器提交上来的文件名是带有路径的,如: c:\a\b\1.txt,而有些只是单纯的文件名,如:1.txt 95//处理获取到的上传文件的文件名的路径部分,只保留文件名部分 96 filename = filename.substring(filename.lastIndexOf("\\")+1); 97//得到上传文件的扩展名 98 String fileExtName = filename.substring(filename.lastIndexOf(".")+1); 99//如果需要限制上传的文件类型,那么可以通过文件的扩展名来判断上传的文件类型是否合法100 System.out.println("上传的文件的扩展名是:"+fileExtName); 101//获取item中的上传文件的输入流102 InputStream in = item.getInputStream(); 103//得到文件保存的名称104 String saveFilename = makeFileName(filename); 105//得到文件的保存目录106 String realSavePath = makePath(saveFilename, savePath); 107//创建一个文件输出流108 FileOutputStream out = new FileOutputStream(realSavePath + "\\" + saveFilename); 109//创建一个缓冲区110byte buffer[] = newbyte[1024]; 111//判断输入流中的数据是否已经读完的标识112int len = 0; 113//循环将输入流读入到缓冲区当中,(len=in.read(buffer))>0就表示in里面还有数据114while((len=in.read(buffer))>0){ 115//使用FileOutputStream输出流将缓冲区的数据写入到指定的目录(savePath + "\\" + filename)当中116 out.write(buffer, 0, len); 117 } 118//关闭输入流119 in.close(); 120//关闭输出流121 out.close(); 122//删除处理文件上传时生成的临时文件 123//item.delete();124 message = "文件上传成功!"; 125 } 126 } 127 }catch (FileUploadBase.FileSizeLimitExceededException e) { 128 e.printStackTrace(); 129 request.setAttribute("message", "单个文件超出最大值!!!"); 130 request.getRequestDispatcher("/message.jsp").forward(request, response); 131return; 132 }catch (FileUploadBase.SizeLimitExceededException e) { 133 e.printStackTrace(); 134 request.setAttribute("message", "上传文件的总的大小超出限制的最大值!!!"); 135 request.getRequestDispatcher("/message.jsp").forward(request, response); 136return; 137 }catch (Exception e) { 138 message= "文件上传失败!"; 139 e.printStackTrace(); 140 } 141 request.setAttribute("message",message); 142 request.getRequestDispatcher("/message.jsp").forward(request, response); 143 } 144145/**146 * @Method: makeFileName 147 * @Description: 生成上传文件的文件名,文件名以:uuid+"_"+文件的原始名称 148 * @Anthor:孤傲苍狼 149 * @param filename 文件的原始名称 150 * @return uuid+"_"+文件的原始名称 151*/152private String makeFileName(String filename){ //2.jpg 153//为防止文件覆盖的现象发生,要为上传文件产生一个唯一的文件名154return UUID.randomUUID().toString() + "_" + filename; 155 } 156157/**158 * 为防止一个目录下面出现太多文件,要使用hash算法打散存储 159 * @Method: makePath 160 * @Description: 161 * @Anthor:孤傲苍狼 162 * 163 * @param filename 文件名,要根据文件名生成存储目录 164 * @param savePath 文件存储路径 165 * @return 新的存储目录 166*/167private String makePath(String filename,String savePath){ 168//得到文件名的hashCode的值,得到的就是filename这个字符串对象在内存中的地址169int hashcode = filename.hashCode(); 170int dir1 = hashcode&0xf; //0--15171int dir2 = (hashcode&0xf0)>>4; //0-15 172//构造新的保存目录173 String dir = savePath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\5 174//File既可以代表文件也可以代表目录175 File file = new File(dir); 176//如果目录不存在177if(!file.exists()){ 178//创建目录179 file.mkdirs(); 180 } 181return dir; 182 } 183184publicvoid doPost(HttpServletRequest request, HttpServletResponse response) 185throws ServletException, IOException { 186187 doGet(request, response); 188 } 189 }
针对上述提出的5点小细节问题进行改进之后,我们的文件上传功能就算是做得比较完善了。
我们要将Web应用系统中的文件资源提供给用户进行下载,首先我们要有一个页面列出上传文件目录下的所有文件,当用户点击文件下载超链接时就进行下载操作,编写一个ListFileServlet,用于列出Web应用系统中所有下载文件。
ListFileServlet的代码如下:
1package me.gacl.web.controller; 2 3import java.io.File; 4import java.io.IOException; 5import java.util.HashMap; 6import java.util.Map; 7import javax.servlet.ServletException; 8import javax.servlet.http.HttpServlet; 9import javax.servlet.http.HttpServletRequest; 10import javax.servlet.http.HttpServletResponse; 1112/**13* @ClassName: ListFileServlet 14* @Description: 列出Web系统中所有下载文件 15* @author: 孤傲苍狼 16* @date: 2015-1-4 下午9:54:40 17* 18*/19publicclass ListFileServlet extends HttpServlet { 2021publicvoid doGet(HttpServletRequest request, HttpServletResponse response) 22throws ServletException, IOException { 23//获取上传文件的目录24 String uploadFilePath = this.getServletContext().getRealPath("/WEB-INF/upload"); 25//存储要下载的文件名26 Map<String,String> fileNameMap = new HashMap<String,String>(); 27//递归遍历filepath目录下的所有文件和目录,将文件的文件名存储到map集合中28 listfile(new File(uploadFilePath),fileNameMap);//File既可以代表一个文件也可以代表一个目录 29//将Map集合发送到listfile.jsp页面进行显示30 request.setAttribute("fileNameMap", fileNameMap); 31 request.getRequestDispatcher("/listfile.jsp").forward(request, response); 32 } 3334/**35 * @Method: listfile 36 * @Description: 递归遍历指定目录下的所有文件 37 * @Anthor:孤傲苍狼 38 * @param file 即代表一个文件,也代表一个文件目录 39 * @param map 存储文件名的Map集合 40*/41publicvoid listfile(File file,Map<String,String> map){ 42//如果file代表的不是一个文件,而是一个目录43if(!file.isFile()){ 44//列出该目录下的所有文件和目录45 File files[] = file.listFiles(); 46//遍历files[]数组47for(File f : files){ 48//递归49 listfile(f,map); 50 } 51 }else{ 52/**53 * 处理文件名,上传后的文件是以uuid_文件名的形式去重新命名的,去除文件名的uuid_部分 54 file.getName().indexOf("_")检索字符串中第一次出现"_"字符的位置,如果文件名类似于:9349249849-88343-8344_阿_凡_达.avi 55 那么file.getName().substring(file.getName().indexOf("_")+1)处理之后就可以得到阿_凡_达.avi部分 56*/57 String realName = file.getName().substring(file.getName().indexOf("_")+1); 58//file.getName()得到的是文件的原始名称,这个名称是唯一的,因此可以作为key,realName是处理过后的名称,有可能会重复59 map.put(file.getName(), realName); 60 } 61 } 6263publicvoid doPost(HttpServletRequest request, HttpServletResponse response) 64throws ServletException, IOException { 65 doGet(request, response); 66 } 67 }
这里简单说一下ListFileServlet中listfile方法,listfile方法是用来列出目录下的所有文件的,listfile方法内部用到了递归,在实际开发当中,我们肯定会在数据库创建一张表,里面会存储上传的文件名以及文件的具体存放目录,我们通过查询表就可以知道文件的具体存放目录,是不需要用到递归操作的,这个例子是因为没有使用数据库存储上传的文件名和文件的具体存放位置,而上传文件的存放位置又使用了散列算法打散存放,所以需要用到递归,在递归时,将获取到的文件名存放到从外面传递到listfile方法里面的Map集合当中,这样就可以保证所有的文件都存放在同一个Map集合当中。
在Web.xml文件中配置ListFileServlet
1<servlet>2<servlet-name>ListFileServlet</servlet-name>3<servlet-class>me.gacl.web.controller.ListFileServlet</servlet-class>4</servlet>56<servlet-mapping>7<servlet-name>ListFileServlet</servlet-name>8<url-pattern>/servlet/ListFileServlet</url-pattern>9</servlet-mapping>
展示下载文件的listfile.jsp页面如下:
1<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> 2<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%> 3<!DOCTYPE HTML> 4<html> 5<head> 6<title>下载文件显示页面</title> 7</head> 8 9<body>10<!-- 遍历Map集合 -->11<c:forEach var="me" items="${fileNameMap}">12<c:url value="/servlet/DownLoadServlet" var="downurl">13<c:param name="filename" value="${me.key}"></c:param>14</c:url>15 ${me.value}<a href="${downurl}">下载</a>16<br/>17</c:forEach>18</body>19</html>
访问ListFileServlet,就可以在listfile.jsp页面中显示提供给用户下载的文件资源,如下图所示:
编写一个用于处理文件下载的Servlet,DownLoadServlet的代码如下:
1package me.gacl.web.controller; 2 3import java.io.File; 4import java.io.FileInputStream; 5import java.io.IOException; 6import java.io.OutputStream; 7import java.net.URLEncoder; 8import javax.servlet.ServletException; 9import javax.servlet.http.HttpServlet; 10import javax.servlet.http.HttpServletRequest; 11import javax.servlet.http.HttpServletResponse; 1213publicclass DownLoadServlet extends HttpServlet { 141516publicvoid doGet(HttpServletRequest request, HttpServletResponse response) 17throws ServletException, IOException { 18//得到要下载的文件名19 String fileName = request.getParameter("filename"); //23239283-92489-阿凡达.avi20 fileName = new String(fileName.getBytes("iso8859-1"),"UTF-8"); 21//上传的文件都是保存在/WEB-INF/upload目录下的子目录当中22 String fileSaveRootPath=this.getServletContext().getRealPath("/WEB-INF/upload"); 23//通过文件名找出文件的所在目录24 String path = findFileSavePathByFileName(fileName,fileSaveRootPath); 25//得到要下载的文件26 File file = new File(path + "\\" + fileName); 27//如果文件不存在28if(!file.exists()){ 29 request.setAttribute("message", "您要下载的资源已被删除!!"); 30 request.getRequestDispatcher("/message.jsp").forward(request, response); 31return; 32 } 33//处理文件名34 String realname = fileName.substring(fileName.indexOf("_")+1); 35//设置响应头,控制浏览器下载该文件36 response.setHeader("content-disposition", "attachment;filename=" + URLEncoder.encode(realname, "UTF-8")); 37//读取要下载的文件,保存到文件输入流38 FileInputStream in = new FileInputStream(path + "\\" + fileName); 39//创建输出流40 OutputStream out = response.getOutputStream(); 41//创建缓冲区42byte buffer[] = newbyte[1024]; 43int len = 0; 44//循环将输入流中的内容读取到缓冲区当中45while((len=in.read(buffer))>0){ 46//输出缓冲区的内容到浏览器,实现文件下载47 out.write(buffer, 0, len); 48 } 49//关闭文件输入流50 in.close(); 51//关闭输出流52 out.close(); 53 } 5455/**56 * @Method: findFileSavePathByFileName 57 * @Description: 通过文件名和存储上传文件根目录找出要下载的文件的所在路径 58 * @Anthor:孤傲苍狼 59 * @param filename 要下载的文件名 60 * @param saveRootPath 上传文件保存的根目录,也就是/WEB-INF/upload目录 61 * @return 要下载的文件的存储目录 62*/63public String findFileSavePathByFileName(String filename,String saveRootPath){ 64int hashcode = filename.hashCode(); 65int dir1 = hashcode&0xf; //0--1566int dir2 = (hashcode&0xf0)>>4; //0-1567 String dir = saveRootPath + "\\" + dir1 + "\\" + dir2; //upload\2\3 upload\3\568 File file = new File(dir); 69if(!file.exists()){ 70//创建目录71 file.mkdirs(); 72 } 73return dir; 74 } 7576publicvoid doPost(HttpServletRequest request, HttpServletResponse response) 77throws ServletException, IOException { 78 doGet(request, response); 79 } 80 }
在Web.xml文件中配置DownLoadServlet
1<servlet>2<servlet-name>DownLoadServlet</servlet-name>3<servlet-class>me.gacl.web.controller.DownLoadServlet</servlet-class>4</servlet>56<servlet-mapping>7<servlet-name>DownLoadServlet</servlet-name>8<url-pattern>/servlet/DownLoadServlet</url-pattern>9</servlet-mapping>
function checkType(val) {
var fileName = val;
var seat = fileName.lastIndexOf(".");
var extension = fileName.substring(seat).toLowerCase();
var allowed = [".doc"];
for (var i = 0; i < allowed.length; i++)
{
if (!(allowed[i] != extension))
{
return true;
}
}
alert("不支持" + extension + "格式");
return false;
}
function change(thisValue)
{
var id = thisValue.getAttribute("ID");
if(checkType($.trim($("#"+id).val())))
{
uploadFile(id);
}
}
function uploadFile(fileId) {
var url = "<%=request.getContextPath()%>/hepow/pl/upload.jsp";
$.ajaxFileUpload({
url: url,
secureuri: false,
fileElementId: fileId,
dataType: ‘text‘,
success: function(data, status) {
if($.trim(data.toString())== $.trim("2"))
{
alert("文件大小不能超过10M!");
}
else if($.trim(data.toString()) == $.trim("-1"))
{
alert("上传失败!");
}
else
{
$("[name=FILEPATH]").val($("[name=FILEPATH]").val()+data.split("#")[0]+"#");
$("[name=FILENAME]").val($("[name=FILENAME]").val()+data.split("#")[1]+"#");
$("#uploadFiles").append("<p guidName=‘"+data.split("#")[0]+"‘ fileName=‘"+data.split("#")[1]+"‘ >"+data.split("#")[1]+" <a href=‘javascript:void(0);‘ class=‘deletes‘ deleteid=‘"+$.trim(data.split("#")[0])+"‘>删除</a></p>");
}
},
error: function(data, status, e) {
alert("发生错误!");
}
});
return false;
}
<%
/*
String savaPath1 =request.getRealPath("/WEB-INF/expertUpload");
SmartUploadhelper helper = new SmartUploadhelper(request,response,this.getServletConfig());
List list = helper.getFileNameList();
String fileName = (String)list.get(0);
String guidName = (new GUID()).toString();
int index = fileName.lastIndexOf(".");
String ext = fileName.substring(index);
helper.setSavepath(savaPath1+"/"+guidName+ext);
int count = helper.saveAll();
System.out.println(fileName+ " " +guidName + " " + ext);
out.print("1");
*/
// String ftpServerName = "FTP_SERVER1";
// String ftpUploadPath = "tam/expertUpload/";
String path = request.getRealPath("/")+"\\plfile";
File mk = new File(path);
if(!mk.exists()) mk.mkdir();
// 新建一个SmartUpload对象
SmartUpload su = new SmartUpload();
// 上传初始化
su.initialize(pageContext);
// 设定上传限制
// 1.限制每个上传文件的最大长度。
//su.setMaxFileSize(4000000);
// 2.限制总上传数据的长度。
// su.setTotalMaxFileSize(20000);
// 3.设定允许上传的文件(通过扩展名限制),仅允许doc,txt文件。
// su.setAllowedFilesList("doc,txt");
// 4.设定禁止上传的文件(通过扩展名限制),禁止上传带有exe,bat,jsp,htm,html扩展名的文件和没有扩展名的文件。
// su.setDeniedFilesList("exe,bat,jsp,htm,html,,");
// 上传文件
su.upload();
// 将上传文件全部保存到指定目录,需要先在在Web应用的根目录下,创建一个upload目录
//int count = su.save("/WEB-INF/expertUpload");
String guidName = (new GUID()).toString();
String fileName = "";
String ext = "";
try{
// 提取上传文件信息,同时可保存文件。
for(int i=0;i<su.getFiles().getCount();i++){
com.jspsmart.upload.File file = su.getFiles().getFile(i);
int fileSize = file.getSize();
if(fileSize < 4*1024*1024)
{
// 将文件另存
fileName = file.getFileName();
ext = file.getFileExt();
file.saveAs("/plfile/" + guidName + "." + ext);
//上传到FTP服务器
// FtpFileManager2.setFTPServer(ftpServerName);
// File file_ftp = new File(request.getRealPath("/expertUpload") +"/"+ guidName + "." + ext);
// FtpFileManager2.allFilesUpdateload(ftpUploadPath, file_ftp);
//0成功,1失败,2文件超过最大大小
out.println(guidName + "." + ext+"#"+fileName);
}
else
{
//0成功,1失败,2文件超过最大大小
out.println("2");
}
}
}catch(Exception e){
e.printStackTrace();
out.print("-1");
}
%>
利用Struts2、用数组同时上传多个文件、这里除了点问题,就是上传的文件都是同一个,可能是beg、采用异步方式可以进行处理。
Struts2上传 web.xml的配置
<filter>
<filter-name>cleanup</filter-name>
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
</filter>
<filter>
<filter-name>struts2</filter-name>
<filter-class>
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>cleanup</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
<filter-mapping>
<filter-name>struts2</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
上传页面
<form action="upload.action" method="post" enctype="multipart/form-data">
文件1:<input type="file" name="file"/><br/>
文件2:<input type="file" name="file"/><br/>
文件3:<input type="file" name="file"/><br/>
<input type="submit" value="上传"/>
</form>
Struts 2的配置文件
<constant name="struts.i18n.encoding" value="UTF-8"/>
<constant name="struts.devMode" value="true"/>
<constant name="struts.configuration.xml.reload" value="true"/>
<constant name="struts.multipart.saveDir" value="/tmp"/>
<package name="lichuntao" extends="struts-default">
<action name="upload" class="action.FileAction">
<!-- <interceptor-ref name="fileUpload">
<param name="allowedTypes">
image/bmp,image/png,image/gif,image/jpeg
</param>
</interceptor-ref> -->
<interceptor-ref name="fileUploadStack"/>
<result name="success">/success.jsp</result>
</action>
</package>
Action 中代码
/**
* <p>
* 文件上传Action
*
* @author 李春涛
* @version 个人版
*/
public class FileAction extends ActionSupport {
private File[] file; // 注意此file和jsp页面中file的name一致
private String[] filefileName; // 注意这些属性都和file挂钩的,多个上传文件与对应的文件名
private String[] fileContentType; // 文件域对应的多个文件的类型
public File[] getFile() {
return file;
}
public void setFile(File[] file) {
this.file = file;
}
public String[] getFileFileName() {
return filefileName;
}
public void setFileFileName(String[] fileFileName) {
this.filefileName = fileFileName;
}
public String[] getFileContentType() {
return fileContentType;
}
public void setFileContentType(String[] fileContentType) {
this.fileContentType = fileContentType;
}
/**
* <br>
* 文件上传
*/
@Override
public String execute() throws Exception {
System.out.println("进入Action");
// 保存上传路径
String path = ServletActionContext.getServletContext().getRealPath(
"/photo");
// 创建文件路径
File dir = new File(path);
if (!dir.exists()) {
dir.mkdir();
}
for (int i = 0; i < file.length; i++) {
filefileName[i] = getName(filefileName[i]);
System.out.println("kkkkkkkkkkkkkkkkkkkkk:"+filefileName[i]);
BufferedInputStream in = new BufferedInputStream(
new FileInputStream(file[i]),4096);
BufferedOutputStream out = new BufferedOutputStream(
new FileOutputStream(
new File(path + "\\" + filefileName[i])),4096);
byte b[] = new byte[4096];
while(in.read(b)!=-1){
out.write(b);
}
}
ActionContext.getContext().getSession().put("filefileName",filefileName);
return SUCCESS;
}
/**
* <br>
* 获取文件名称
*/
public String getName(String str) {
int index = str.lastIndexOf(".");
String extesion = str.substring(index);
return new Date().getTime() + extesion;
}
成功页面
上传成功:<br/>
<s:iterator id="img" value="%{#session.filefileName}" status="st">
第<s:property value="#st.getIndex()+1"/>个图片.....
<img src="photo/<s:property value="#img"/>"/><br/>
</s:iterator>
Struts 2 的文件下载
Ø 有的同学可能会想,我只要设置一个超链接,不就可以下载文件了吗?确实如此,但是通过超链接下载文件,暴露了下载文件的真实地址,不利于对资源进行安全保护;而且利用超链接下载文件,服务器端的文件只能存放在Web应用程序所在的目录下。
Ø 利用程序编码实现下载,可以增加安全访问控制,对经过授权认证的用户提供下载,还可以任意提供下载的数据,我们可以将文件放到Web应用程序以外的目录中,也可以将文件保存到数据库中。
Ø 利用程序下载也非常简单,只需要按照如下的方式设置三个报头域就可以了:
Ø Content-Type:application/x-msdownload
Ø Content-Disposition:attachment;filename=downloadfile
Ø Content-Length:filesize
Ø 浏览器在接收到上述的报头信息后, 就会弹出文件下载对话框,让你将文件保存到本地硬盘
Can not find a java.io.InputStream with the name [inputStream] in the invocation stack. Check the <param name="inputName"> tag specified for this action.
1.文件路径不对,根本就没有取到文件。这种情况下,可以将获得InputStream的那条语句放在system.out.println()中输出一下,若为null,那就是路径不对了,或者说得准确些就根本没有找到文件。
2.在action中没有写配置文件中"<param name="inputName">"后面属性的那个get方法.
当以上两种情况都正确的情况下,问题就在这里了:
当采用 return ServletActionContext.getServletContext().getResourceAsStream("...") 这种方法获得输入流的时候,要保证文件位置在 ServletContext 当中,就是说要在当前的应用上下文中,
如果想要获得外部文件 譬如 D盘中的某个文件,那么就要自己创建输入流才可以,如:
File file = new File("D:\\spring.doc");
InputStream is = new FileInputStream(file);
return is;
File file = new File("D:\\spring.doc"); InputStream is = new FileInputStream(file); return is;
则OK!!
<a href="download.action">我要下载</a>
<action name="download" class="action.DownLoadAction">
<!-- 指定下载目录,相对于webRoot的目录 -->
<param name="inputPath">/1.zip</param>
<!-- 使用StreamResult结果类型 -->
<result name="success" type="stream">
<!-- 指定下载内容的文件的类型 -->
<param name="contentType">application/zip</param>
<!-- inputName的默认值是inputStream,如果action中用于读取下载文件的属性明是inputStream,那么可以省略这个参数
-->
<param name="inputName">inputStream</param>
<param name="contentDisposition">filename="1.zip"</param>
<param name="buferSize">2048</param>
</result>
</action>
public class DownLoadAction extends ActionSupport{
private String inputPath; //文件的路径,在Struts2配置文件中配置
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
public String getInputPath() {
return inputPath;
}
//StreamResult结果集类型使用该方法读取数据
public InputStream getInputStream() throws Exception{
File file = new File(inputPath);
if(file.exists())System.out.println("存在 啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊");
System.out.println("asdfasdfds"+ServletActionContext.getServletContext().getResourceAsStream(inputPath));
returnServletActionContext.getServletContext().getResourceAsStream(inputPath);
}
//核心方法
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
return SUCCESS;
}
bytes = FileUtils.readFileToByteArray(new File(reviewBookBaseDIR,
acc.getZipName()));
// 清空response
response.reset();
byte[] tempByte = String.valueOf(acc.getZipName()).getBytes("GBK");
String tempStr = new String(tempByte, "ISO8859_1");
// 设置response的Header
response.setContentType("application/octet-stream");
response.addHeader("Content-disposition", "attachment;filename="
+ tempStr);
response.addHeader("Content-length", "" + bytes.length);
response.setStatus(200);
OutputStream toClient = new BufferedOutputStream(
response.getOutputStream());
toClient.write(bytes);
toClient.flush();
toClient.close();
Struts 2 文件上传详解
. 在处理文件上传的Action中,如果想把上传文件统一存放在upload目录,应该怎样设置?
错误1:使用相对路径
按习惯保存文件会使用相对路径,即"./upload"或"upload",但经测试,按这种方式写,实际上upload文件加是在eclipse软件根目录下建立的,并未在web工程下建立,这尼玛让我去哪访问,此方法PASS!
错误2:使用旧方法获得绝对路径
按书上的例子,应该使用绝对路径获得web应用的根来保存上传文件
Java代码
但在最新Servlet-API中,request.getRealPath()方法已经不推荐使用,再网上查替代方法,思路有了,但代码写的比这个还长,这是坑爹呢~
正确方法:使用新方法获得绝对路径
在网上能查到的使用新方法获得绝对路径的方法很多,推荐Struts2开发中设置Action继承ServletContextAware(Action内部即可直接使用ServletContext对象)
Java代码
代码看起来还算清晰,漂亮!
说明:在eclipse(wtp)开发环境下运行,实际realPath的结果出乎意料,尼玛竟然是这样,虽然不记,但好在这个地址真是web应用的“真实”地址,是好用的,忍了!
Java代码
2.其他页面如何调用显示保存的图片?
首先要求图片按步骤1中说的那样,保存在web应用根目录下
Html代码
3.Struts2配置文件中的struts.multipart.saveDir起什么作用?
原来初步感觉这个文件夹就服务端保存上传文件的文件夹,不过根本不是这么回事!
这个文件夹只是用来保存上传文件的“临时路径”,文件上传完毕后就会从此路径移除。
如果不配置将使用默认的 javax.servlet.context.tempdir 来保存临时文件。
标签:
原文地址:http://www.cnblogs.com/Lichuntao/p/5188717.html