struts2-上传与下载
?
?关于struts2-上传与下载?
一、struts2的上传下载是如何实现的?:其实struts2框架中的下载是基于commons.fileupload.jar 和 commons.io.jar来实现的它只是将某些复
? ?杂的逻辑代码封装起来,并且简化从而利于开发者的开发。
二、struts2上传下载的核心是怎么样的???1.struts2上传下载的核心是由commons.fileupload中的ServletFileUpload和DiskFileItemFactory类
??来实现(在commons.fileupload.jar中以前的版本,主要使用的是FileUpload类。新的版本提倡使用??FileUpload的子类ServletFileUpload)
? 2.DiskFileItemFacotry需要设置两个参数
? ?:Repository:创建一个文件上传的缓存目录
? ?SizeThreshold:设置在缓存中的文件大小
?
? 3.ServletFileUpload实现它的一个有参构造方法
? ?:参数为FileItemFactory(它是一个接口) DiskFileItemFactory实现了这个接口
? ?:通过ServletFileUpload类的parseRequest()方法获取一个List<FileItem>集合,通过对集合的遍历解
? ??析获取表单中的信息
? 4.下面提供一个以Servlet和jsp 使用commons.fileupload 和commons.io 实现的上传功能
? ?Servlet:(UploadServlet)
package org.svse.servlet;
import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;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.FileUpload;import org.apache.commons.fileupload.FileUploadException;import org.apache.commons.fileupload.disk.DiskFileItemFactory;import org.apache.commons.fileupload.servlet.ServletFileUpload;public class UploadServlet extends HttpServlet {@Override@SuppressWarnings("unchecked")protected void doPost(HttpServletRequest req, HttpServletResponse resp)throws ServletException, IOException {/* * 注意,当jsp中表单的enctype设置的为:multipart/form-data的时候 我们无法直接使用 * request.getParameter("") 获取表单的数据信息 */// 使用DiskFileItemFacotry类进行表单的处理,以及文件的上传DiskFileItemFactory disk = new DiskFileItemFactory();// 获取WebRoot目录下的upload文件夹的路径String path = req.getRealPath("/upload");disk.setRepository(new File(path));// 设置上传文件的缓存目录disk.setSizeThreshold(1024 * 1024); // 设置文件的大小,如果超过这个大小,文件则会直接向硬盘存入// 借助ServletFileUpload 进行表单的解析,与文件的流的处理ServletFileUpload upload = new ServletFileUpload(disk);try {List<FileItem> list = upload.parseRequest(req);// List<FileItem>中保存着有关表单元素的所有信息 需要对它进行遍历for (FileItem item : list) {// item.isFormField() 判断该元素是不是表单的一个字段 如果是 则可以直接取得它的名称和内容if (item.isFormField()) {String name = item.getFieldName();/* * 获取该字段的名称 如:<input type="text" name="password"/> * 该方法便是获取name属性的值 :password */String value = item.getString("gbk");/* 获取该字段的value属性的值 */req.setAttribute(name, value);} else// else则证明它是一个file文件流{String name = item.getFieldName();String value = item.getName();/* * 对于表单中的file元素,我们不能通过getString获取它的内容,因为它是一个流 * 只能够通过getName方法获取当前文件的名称 */int start = value.lastIndexOf("\\");// 对value进行处理,由于某些浏览器 可能只显示 文件名+后缀// 有的则将文件的全部路径都显示出来 ,所以我们要在这里对它进行一次通用处理String filename = value.substring(start + 1);// 记住一定要将start+1 因为start的位置对应的是'\\'req.setAttribute(name, filename);// 创建输入流 与 输出流InputStream input = item.getInputStream();byte[] buffer = new byte[1024];int length = 0;OutputStream os = new FileOutputStream(new File(path,filename));// 开始读取并写入信息while ((length = input.read(buffer)) > 0) {os.write(buffer, 0, length);}// 一次关闭流os.close();input.close();// 上传完毕System.out.println("Upload Over!");}}} catch (FileUploadException e) {// TODO Auto-generated catch blocke.printStackTrace();}// 请求转发req.getRequestDispatcher("/upload/result.jsp").forward(req, resp);}}? Jsp:(upload.jsp)
<form action="/struts2/upload" method="post"enctype="multipart/form-data">//一定要设置form表单的 //method属性和enctype实行 UserName:<input type="text"name="username" id="username" /><br /> Password:<input type="password"name="password" id="password" /><br /> File: <input type="file"name="file" id="file" /><br /> <input type="submit" value="submit" /></form>??三、如何使用struts2封装后的上传与下载: 1.上传a):对于struts2中的上传主要是由struts-default.xml中名为:fileUpload的拦截器实现的通过拦截客户端的请求,获取数据信息实现上传功能。b):实现的主要步骤1.我们需要创建一个对应上传的Action,在Action中我们需要定义三个字段用于存储表单中文件的信息如下:如果页面(<input type="file" name="upload">表单中的file元素名为:upload,那么我们需要在Action中定义如下字段private File upload;//对应文件流 ?根据表单的中的file元素的name属性值命名private String uploadFileName; ?//对应文件的名称 表单name属性值+FileNameprivate String uploadContentType; //对应文件的类型 表单name属性值+ContentType/*命名规范是固定,并且要实现它们的getter 和 setter方法 可以参看fileUpload拦截器对应的? ? ? ??Interceptor类中代码主要用于拦截器为定义的属性进行赋值,以及后面的调用*/2.我们需要在struts.xml 文件中配置一个对应上传的<Action>如下:在定义的Action标签中需要添加名为 fileUpload的拦截器,并为它的属性进行赋值。
<interceptor ref="fileUpload">//可以设置 上传文件的类型,最大大小,/*在FileUploadInterceptor 源代码中 有如下片段实例 * <ul> * <p/> * <li>maximumSize (optional) - the maximum size (in bytes) that the interceptor will allow a file reference to be set * on the action. Note, this is <b>not</b> related to the various properties found in struts.properties. * Default to approximately 2MB.</li> * <p/> * <li>allowedTypes (optional) - a comma separated list of content types (ie: text/html) that the interceptor will allow * a file reference to be set on the action. If none is specified allow all types to be uploaded.</li> * <p/> * <li>allowedExtensions (optional) - a comma separated list of file extensions (ie: .html) that the interceptor will allow * a file reference to be set on the action. If none is specified allow all extensions to be uploaded.</li> * </ul> maximumSize:设置单个上传文件的最大字节,struts2中默认的总上传文件的大小为2097152字节(2M) 我们可以通过 <Constant name="struts.multipart.maxSize" value="">value指定大小 ,单位为字节 allowedTypes:设置上传文件的类型 上传的文件类型可以参考tomcat中web.xml配置中的文件类型信息 属性值 如:application/vnd.ms-powerpoint 代表文件的类型为ppt allowedExtensions:设置文件的扩展名,同上一个属性的效果是一样的,不过它的属性值更加 直观易懂 如: .ppt */ <param name="allowedExtensions">.ppt,.txt</param>//使用<param>标签进行赋值 <param name="maximumSize">409600</param>//上传单个文件的最大字节 </interceptor ref>?3.一个使用struts2的上传实例:Action:
package org.svse.action;import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.InputStream;import java.io.OutputStream;import java.util.List;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.ActionSupport;public class UploadAction extends ActionSupport {private String username;private String password;/* * 如果每次只上传一个文件 就可以使用上面介绍的代码 * * 这里义的泛型集合,是为了上传多个文件,也可以用数组 如: * privaet File [] file; * private String [] fileFileName; * private String [] fileContentType; */private List<File> file;private List<String> fileFileName;private List<String> fileContentType;/* * 为什么要定义fileFileName 和filecontextType 这里是用于FileUpload的拦截器的赋值 */public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public List<File> getFile() {return file;}public void setFile(List<File> file) {this.file = file;}public List<String> getFileFileName() {return fileFileName;}public void setFileFileName(List<String> fileFileName) {this.fileFileName = fileFileName;}public List<String> getFileContentType() {return fileContentType;}public void setFileContentType(List<String> fileContentType) {this.fileContentType = fileContentType;}@Overridepublic String execute() throws Exception {// 指定上传的位置String path = ServletActionContext.getRequest().getRealPath("/upload");for (int i = 0; i < file.size(); i++) {// 获取输入流InputStream is = new FileInputStream(file.get(i));byte[] buffer = new byte[1024];int length = 0;// 创建输出流对象OutputStream os = new FileOutputStream(new File(path, this.getFileFileName().get(i)));// 开始上传while ((length = is.read(buffer)) > 0) {os.write(buffer, 0, length);}// 一次关闭流os.close();is.close();}// 返回结果return SUCCESS;}}?View : upload2.jsp<%@ page language="java" import="java.util.*" pageEncoding="GB18030"%><%@ taglib prefix="s" uri="/struts-tags"%><!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"><html><head><title>My JSP 'upload2.jsp' starting page</title><meta http-equiv="pragma" content="no-cache"><meta http-equiv="cache-control" content="no-cache"><meta http-equiv="expires" content="0"><meta http-equiv="keywords" content="keyword1,keyword2,keyword3"><meta http-equiv="description" content="This is my page"><script type="text/javascript">function addMore() //触发此方法后添加一个,file元素{var td= document.getElementById("more");var br=document.createElement("br");var input = document.createElement("input");var button = document.createElement("input");input.type="file";input.name="file";button.type="button";button.value="Remove";button.onclick=function ()//为Remove按钮注册一个点击事件{td.removeChild(br);td.removeChild(input);td.removeChild(button);}td.appendChild(br);td.appendChild(input);td.appendChild(button);}</script></head><body style="text-align: center"><div style="text-align: left"><s:fielderror cssStyle="color:red"></s:fielderror><s:actionerror /></div><s:form action="upload" method="post" enctype="multipart/form-data"theme="simple"><table border="1" width="80%"><tr><td>UserName:</td><td><s:textfield name="username"></s:textfield></td></tr><tr><td>PassWord:</td><td><s:password name="password"></s:password></td></tr><tr><td>File1:</td><td id="more"><s:file name="file"></s:file> <inputtype="button" value="Add More" onclick="addMore()"></td></tr><tr><td><s:submit value="Submit"></s:submit></td><td></td></tr></table></s:form></body></html>?struts.xml的配置信息
<struts><constant name="struts.multipart.saveDir" value="e:\"></constant>//设置缓存文件的存放位置(当上传完成后,会被自动删除)<constant name="struts.i18n.encoding" value="gbk"></constant> //设置编码格式<constant name="struts.custom.i18n.resources" value="message"></constant>//当上传失败的时候,可以在指定的message.properties中定义显示的错误信息<package name="struts2" extends="struts-default"><action name="upload" name="code">//当上传的文件太大,或者文件类型不符合规定的时候我们可以自定义一个资源文件//根据struts-message.properties中的默认属性名 在自己定义的资源文件中给这些属性重新赋值struts.messages.error.file.too.large=File too large: {0} "{1}" "{2}" {3}//当文件太大的时候抛出的错误信息struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}//文件类型不符合规定的时候抛出的错误信息struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}//当文件的扩展名不符合规定的时候抛出的错误信息//注意这些错误都是FieldError级别的 如果希望在页面上显示,那么就要使用 <s:fielderror>标签 4.介绍一下关于defalut.properties 中的struts.multipart.maxSize 和 fileUpload中的
maximumSize的区别!
?
1.struts.multipart.maxSize掌控整个项目所上传文件的最大的Size。超过了这个size,后台报
错,程序处理不了如此大的文件。ActionError里面会有如下的提示:
the request was rejected because its size (16272982) exceeds the configured
maximum (9000000)
?
2.fileUpload拦截器的maximumSize属性必须小于struts.multipart.maxSize的值。
struts.multipart.maxSize默认2M,当maximumSize大于2M时,必须设置
struts.multipart.maxSize的值大于maximumSize。
?
3.当上传的文件大于struts.multipart.maxSize时,系统报错
当上传的文件在struts.multipart.maxSize和maximumSize之间时,系统提示:
File too large: file "MSF的
?
?
2.下载a):关于下载主要是有struts-default.xml中的<result-type name="stream"
name="code">//StreamResult类中的字段源码/*protected String contentType = "text/plain";//设置下载文件的类型protected String contentLength;//设置文件的大小protected String contentDisposition = "inline";//设置下载的时候显示的文件名protected String contentCharSet ;//设置编码格式protected String inputName = "inputStream";//设置对应下载的Action类中获取java.io.InputStream的类的名称 在Action中该类的名称最好为:// public InputStream getInputStream(){}protected int bufferSize = 1024;//设置下载缓冲大小*/
? ? ? ?2.具体实例如下:
struts.xml:
<action name="download" type="stream"><param name="contentType">application/vnd.ms-powerpoint</param>//这里的赋值方式 与 fileUploadInterceptor的allowedTypes方式相同<param name="contentDisposition">filename="${fileNames}"</param>/*${fileNames} 这个el表达是是为了获取Action中 getFileNames()方法的返回值该方法是为了解决文件乱码实现的*/<param name="inputName">inputStream</param>/*inputStream 是为了获取对应Action 中的getInputStream()方法的返回值该返回值的类型为 java.io.InputStream*/<param name="bufferSize">4096</param></result></action>?Action:
package org.svse.action;import java.io.InputStream;import java.io.UnsupportedEncodingException;import org.apache.struts2.ServletActionContext;import com.opensymphony.xwork2.Action;import com.opensymphony.xwork2.ActionContext;import com.opensymphony.xwork2.ActionSupport;public class DownloadAction extends ActionSupport {private String pathName; // 该字段是为了获取页面传过来的文件名称的信息public String getPathName() {return pathName;}public void setPathName(String pathName) {this.pathName = pathName;}public String getFileNames() throws Exception {// 返回文件的名称 给<param// name="contentDisposition">filename="${fileNames}"</param>return this.getPathName();}public InputStream getDownload() throws Exception {// 这里是一个重点 获取一个输入流return ServletActionContext.getServletContext().getResourceAsStream("/upload/"/* 获取WebRoot/upload/的某一个文件 */+ new String(this.getPathName().getBytes("iso-8859-1"),"gb18030"));// new String(this.getPathName().getBytes("iso-8859-1"),"gb18030")// 将文件名进行转码 转换成简体中文// 当没有找到该文件对象的时候 会抛出/* * Can not find a java.io.InputStream with the name [download] in the * invocation stack. Check the <param name="inputName"> tag specified * for this action. */}@Overridepublic String execute() throws Exception {return SUCCESS;}}?Jsp (upload2.jsp)
<a href="/struts2/download.action?pathName=第四讲.ppt">下载一</a><a href="/struts2/download.action?pathName=12.txt">下载二</a>/*pathName=第四讲.ppt对Action中的pathName属性进行赋值,用于指定下载哪一个文件*/ 3 楼 PerfectPlan 2012-06-17 fancy2010love 写道// 获取WebRoot目录下的upload文件夹的路径29. String path = req.getRealPath("/upload");
req.getRealPath这个方法已经过时了,应该不建议再使用吧
嗯嗯,是不建议是用了。以前写的,谢谢建议哦