【Struts2】Struts2学习(6)文件上传和下载

来源:互联网 发布:bartender vb脚本示例 编辑:程序博客网 时间:2024/05/20 19:29

Struts2的文件上传

Struts2没有提供自己的请求解析器,也就是说,Struts2不会自己去处理multipart/form-data请求,它需要调用其他上传框架来解析而简直数据。

Struts2配置文件上传解析器

#指定使用COS的文件上传解析器#struts.multipart.parser=cos#指定使用pell的文件上传解析器#struts.multipart.parser=pell#struts2默认使用Jakarta的 Common-FileUpload文件上传解析器struts.multipart.parser=jakarta

Struts2 封装隔离了底层文件上传组件的区别,开发者只要在此处配置上传所使用的解析器,就可以切换不同文件上传框架。

文件上传页面,包含两个表单域,文件标题和文件域。

<s:form action="uploadPro"enctype="multipart/form-data"><s:textfield name="title" label="文件标题"/><br /><s:file name="upload" label="选择文件"/><br /><s:submit value="上传"/></s:form>
处理上传的Action

public class UploadAction extends ActionSupport{//封装文件标题请求参数的属性private String title;//封装上传文件域的属性private File upload;//封装上传文件类型的属性private String uploadContentType;//封装上传文件名的属性private String uploadFileName;//直接在struts.xml文件中配置的属性private String savePath;//接受struts.xml文件配置值的方法public void setSavePath(String value){this.savePath = value;}//返回上传文件的保存位置private String getSavePath() throws Exception {return ServletActionContext.getServletContext().getRealPath(savePath);}//文件标题的setter和getter方法public void setTitle(String title) {this.title = title; }public String getTitle(){return (this.title); }//上传文件对应文件内容的setter和getter方法public void setUpload(File upload) {this.upload = upload; }public File getUpload() {return (this.upload); }//上传文件的文件类型的setter和getter方法public void setUploadContentType(String uploadContentType) {this.uploadContentType = uploadContentType; }public String getUploadContentType(){return (this.uploadContentType); }//上传文件的文件名的setter和getter方法public void setUploadFileName(String uploadFileName) {this.uploadFileName = uploadFileName; }public String getUploadFileName() {return (this.uploadFileName); }@Overridepublic String execute() throws Exception{//以服务器的文件保存地址和原文件名建立上传文件输出流FileOutputStream fos = new FileOutputStream(getSavePath()+ "\\" + getUploadFileName());FileInputStream fis = new FileInputStream(getUpload());byte[] buffer = new byte[1024];int len = 0;while ((len = fis.read(buffer)) > 0){fos.write(buffer , 0 , len);}fos.close();return SUCCESS;}}
除了和表单对应的upload和title两个属性,上面的Action还包含了两个属性:uploadFileName 和uploadContentType ,这两个属性分别用来封装上传文件的文件名、上传文件的文件类型。 savePath属性用来配置保存位置,该属性的值用配置文件来设置。

<struts><constant name="struts.custom.i18n.resources" value="mess"/><!-- 设置该应用使用的解码集 --><constant name="struts.i18n.encoding" value="GBK"/><package name="lee" extends="struts-default"><!-- 配置处理文件上传的Action --><action name="uploadPro" class="org.crazyit.app.action.UploadAction"><!-- 动态设置Action的属性值 --><param name="savePath">/uploadFiles</param><!-- 配置Struts 2默认的视图页面 --><result>/WEB-INF/content/succ.jsp</result></action><action name="*"><result>/WEB-INF/content/{1}.jsp</result></action></package></struts>

手动实现文件过滤

Web应用不允许浏览者自由上传,所以我们需要对上传的文件类型和大小进行限制。

在Action中定义一个用于进行文件过滤的方法,该方法逻辑用于判断上传文件的类型是否是允许类型。

public String filterTypes(String[] types){//获取希望上传的文件类型String fileType = getUploadContentType();for (String type : types){if (type.equals(fileType)){return null;}}return ERROR;}
为了让程序可以动态配置允许上传的文件列表,为Action增加一个allowTypes属性,该属性列出了所有允许上传的文件类型,可以在struts.xml中配置。

//定义该Action允许上传的文件类型private String allowTypes;//allowTypes属性的setter和getter方法public String getAllowTypes(){return allowTypes;}public void setAllowTypes(String allowTypes){this.allowTypes = allowTypes;}
利用Struts2的输入校验来判断用户输入的文件是否符合要求,如果不符合要求,就将错误提示添加到FieldError中。Action中增加validate()方法。

//执行输入校验public void validate(){//将允许上传文件类型的字符串以英文逗号(,)//分解成字符串数组从而判断当前文件类型是否允许上传String filterResult = filterTypes(getAllowTypes().split(","));//如果当前文件类型不允许上传if (filterResult != null){//添加FieldErroraddFieldError("upload" , "您要上传的文件类型不正确!");}}
为了让文件类型校验失败时能返回input逻辑视图,必须为该Action增加input逻辑视图逻辑配置。

<package name="lee" extends="struts-default"><!-- 配置处理文件上传的Action --><action name="uploadPro" class="org.crazyit.app.action.UploadAction"><!-- 动态设置Action的属性值 --><param name="savePath">/uploadFiles</param><param name="allowTypes">image/png,image/gif,image/jpeg</param><result name="input">/WEB-INF/content/upload.jsp</result><!-- 配置Struts 2默认的视图页面 --><result>/WEB-INF/content/succ.jsp</result></action><action name="*"><result>/WEB-INF/content/{1}.jsp</result></action></package>

拦截器实现文件过滤

Strtus2提供了一个文件上传的拦截器,通过配置该拦截器可以更轻松的实现文件过滤。

配置fileUpload拦截器时,可以为其指定两个参数。

allowTypes:该参数指定允许上传的文件类型,多个文件类型之间以英文逗号隔开。

maximumSize:该参数指定允许上传的文件大小,单位是字节。

<package name="lee" extends="struts-default"><!-- 配置处理文件上传的Action --><action name="uploadPro" class="org.crazyit.app.action.UploadAction"><!-- 配置fileUpload拦截器--><interceptor-ref name="fileUpload"><param name="allowedTypes">image/png,image/gif,image/jpeg,image/bmp</param><!-- 配置允许上传的文件大小 --><param name="maximumSize">2000000</param></interceptor-ref><interceptor-ref name="defaultStack"></interceptor-ref><!-- 动态设置Action的属性值 --><param name="savePath">/uploadFiles</param><param name="allowTypes">image/png,image/gif,image/jpeg</param><result name="input">/WEB-INF/content/upload.jsp</result><!-- 配置Struts 2默认的视图页面 --><result>/WEB-INF/content/succ.jsp</result></action><action name="*"><result>/WEB-INF/content/{1}.jsp</result></action></package>

使用Struts2控制文件下载

Struts2提供了stream结果类型,该结果类型是专门用于支持文件下载功能的。

文件下载Action,该Action提供一个返回InputStream流的方法。

public class FileDownloadActionextends ActionSupport{//该属性可以在配置文件中动态指定该属性值private String inputPath;//依赖注入该属性值的setter方法public void setInputPath(String value){inputPath = value;}/*定义一个返回InputStream的方法,该方法将作为被下载文件的入口,且需要配置stream类型结果时指定inputName参数,inputName参数的值就是方法去掉get前缀、首字母小写的字符串*/public InputStream getTargetFile() throws Exception {//ServletContext提供getResourceAsStream()方法//返回指定文件对应的输入流 return ServletActionContext.getServletContext().getResourceAsStream(inputPath);}}

配置文件下载Action,关键是需要配置一个类型为stream的结果,该stream类型的结果将使用文件下载作为响应。配置stream类型的结果需要指定如下四个属性:

contentType: 指定被下载文件的文件类型。

inputName:指定被下载文件的入口输入流。

contentDisposition:指定下载的文件名。

bufferSize:指定下载文件时的缓冲大小。

配置stream类型的结果时,因为无需指定实际显示的物理资源,所以无需指定location属性只需要指定inputName属性,该属性代表被下载文件的入口。
<action name="download" class="org.crazyit.app.action.FileDownloadAction"><!-- 指定被下载资源的位置 --><param name="inputPath">\images\疯狂联盟.jpg</param><!-- 配置结果类型为stream的结果 --><result name="success" type="stream"><!-- 指定下载文件的文件类型 --><param name="contentType">image/jpg</param><!-- 指定由getTargetFile()方法返回被下载文件的InputStream --><param name="inputName">targetFile</param><!-- 默认为 inline(在线打开),设置为 attachment 将会告诉浏览器下载该文件,filename 指定下载文                                                                             件保有存时的文件名,若未指定将会是以浏览的页面名作为文件名,如以 download.action 作为文件名 -->  <param name="contentDisposition">attachment;filename="wjc_logo.jpg"</param><!-- 指定下载文件的缓冲大小 --><param name="bufferSize">4096</param></result></action>

下载前的授权控制

应用程序可以在下载文件之前,先通过Action来检查用户是否有权下载该文件。

public class AuthorityDownActionimplements Action {private String inputPath;public void setInputPath(String value){inputPath = value;}public InputStream getTargetFile() throws Exception {//ServletContext提供getResourceAsStream()方法//返回指定文件对应的输入流 return ServletActionContext.getServletContext().getResourceAsStream(inputPath);}public String execute() throws Exception{//取得ActionContext实例ActionContext ctx = ActionContext.getContext();//通过ActionContext访问用户的HttpSessionMap session = ctx.getSession();String user = (String)session.get("user");//判断Session里的user是否通过检查if ( user !=  null && user.equals("limeng")){return SUCCESS;}ctx.put("tip", "您还没有登录,或者登录的用户名不正确,请重新登录!");return LOGIN;}}
访问时execute方法进行判断,如果登陆了则可以下载,没有登录则会跳转到登录页面。

<action name="download2" class="org.crazyit.app.action.AuthorityDownAction"><!-- 定义被下载文件的物理资源 --><param name="inputPath">\images\wjc_logo.zip</param><result name="success" type="stream"><!-- 指定下载文件的文件类型 --><param name="contentType">application/zip</param><!-- 指定由getTargetFile()方法返回被下载文件的InputStream --><param name="inputName">targetFile</param><param name="contentDisposition">filename="wjc_logo.zip"</param><!-- 指定下载文件的缓冲大小 --><param name="bufferSize">4096</param></result><!-- 定义一个名为login的结果 --> <result name="login">/WEB-INF/content/login.jsp</result></action>

LoginAction登陆后会把用户名保存在session里,然后跳转到下载页面,下载页面执行execue方法,判断该用户是否有权限下载文件,有则下载,没有则跳转到登录页面,提示没有登录或者该用户没有权限下载文件。