Struts2文件上传和下载

allen3106 贡献于2011-05-16

作者 MC SYSTEM  创建于2011-05-03 02:29:00   修改者MC SYSTEM  修改于2011-05-03 05:58:00字数10866

文档摘要:目前主要使用的MVC开源架构是Struts,所以这里笔者就以Struts2为例,讲解下关于Struts2的文件上传和下载的机制。
关键词:

Struts2 File Upload and Download 上一篇 / 下一篇  2010-04-15 22:42:06 / 个人分类:JEE 查看( 693 ) / 评论( 0 ) / 评分( 0 / 0 )         记得自己当年自学JSP的时候看到文件上传和下载的时候自己很激动,因为基本上任何系统里面都或有这个功 能模块,所以当时就看的很仔细,当初还使用的是SmartUpload,当自己后来慢慢的接触后,逐步对文件的上传和下 载有了重新的认识和体会,目前主要使用的MVC开源架构是Struts,所以这里笔者就以Struts2为例,讲解下关于 Struts2的文件上传和下载的机制。         如果大家要使用struts2的文件上传功能那么需要导入commons-fileupload.jar和commons-io.jar文件,如 果你使用的是Struts2的最小依赖包,这里可以不用再额外导入!         我们首先看下struts2默认支持的有那些开源的第三方的文件上传和下载,在struts的核心包中的 default.properties中我们可以看到如下片段:             # struts.multipart.parser=cos           yt YdP7{0            # struts.multipart.parser=pell c)^ H7x:] {@/{;D0               struts.multipart.parser=jakarta中文JAVA技术网-Z`n/S+@km(@f?             # uses javax.servlet.context.tempdir by default中文JAVA技术网!~&X#{;MHXM+v1W7vq$c                struts.multipart.saveDir= G3k:Q ws J0               struts.multipart.maxSize=2097152           #在properties中代表注释,其中cos是著名的Oreilly组织开发的,这里大家可以获取以下几点信息:              1、properties中的注释怎么写?               2、struts2默认都支持哪几种文件上传和下载              3、上传文件的临时目录默认是没有的              4、struts2的默认上传和下载使用的是jakarta下的commons-fileupload组件,最大允许一次上传的文件大小为                2M多一点(配置中以字节为单位)!         当然了大家如果要使用其他的上传组件,可以将相关的语句注释删除,给默认的添加#,并导入相关的jar就可 以了,这就是struts2的灵活性!         在讲具体的文件上传的时候大家要考虑一个问题: 当一个参数是文件时,传统的表单字段是否可行?传统表单字 段值的获取方式是否可行?          很明显传统的获取表单的一套方法这里已经不可使用了,因为文件是二进制字节流,所以这里先给大家讲解下 基于web的几种字段编码方式:           1、 application/x-www-form-urlencoded 我们一般的默认的使用的编码方式 URL编码           2、 multipart/form-data主要用于以二进制流的方式传输表单字段的数据           3、 text/plain 主要用于直接通过表单发送邮件 如:mailto:          所以这里大家在做文件的时候一定要清楚一点你的表单的编码方式一定要采用第2种,否则就会出现问题!         Struts2上传页面upload.jsp          9{.B-h E0|0        Sv0x,r,G7`0         中文JAVA技术网Q8s\cP          中文JAVA技术网Q K/O3W^         中文JAVA技术网bXXbw7j$I a                  这里笔者故意设置了一个一般字段和多个文件字段(2), 因为笔者在刚开始使用SmartUpload的时候就遇到这样的 问题,如果上传的文件字段和一般的普通表单字段放在一起的时候不能获取一般的表单字段,当初刚使用 SmartUpload的时候没有看它的API,后面有时间看的时候才发现要使用组件自带的request对象,随意这里大家就要 注意struts2的文件上传了。第二点是直接看下struts2对文件的批量上传的处理,有些人就不明白了?为什么要直接讲 多文件上传呢? 呵呵,因为在struts2中单个文件上传和多文件的上传是一致的,只要会一个,另一个就显的很简单 了!           处理的文件上传的action:UploadAction.java           public class UploadAction extends ActionSupport{中文JAVA技术网m2?,@_XF9m)@           private List upload;中文JAVA技术网 nE@!Y J%~H k1M9CV4apF           private String path;中文JAVA技术网yeR] p,m@7[           private String info;中文JAVA技术网-M/TgE Eua [&a           private List uploadContentType;中文JAVA技术网5R@1?J&o$L1V           private List uploadFileName;                      // 当然这里可以使用数组           get、set();           public String getPath() {中文JAVA技术网zbS!mK&rg           return ServletActionContext.getRequest().getRealPath(path);    //  获取存放路径的绝对路径中文JAVA技术网"s/uV uClG           }           public void upload(int i) throws Exception{中文JAVA技术网0Z`,wn+bg QB e           InputStream fio=new FileInputStream(upload.get(i));中文JAVA技术网9x0Ew$m3t:D;\7dM          OutputStream fou=new FileOutputStream(getPath()+"\\"+uploadFileName.get(i));中文JAVA技术网;m k+o A;{          System.out.println(getPath()+"\\"+upload.get(i).getName()); :n,D]$T+B']-^x0         byte [] buf=new byte[1024]; m/bNs/U)bD?|0         int length=0;中文JAVA技术网|pTr|!O          while((length=fio.read(buf))>0){ (lc.J8W1`?"j0         fou.write(buf,0,length); 4@/[(B:Jy^0         } T|)E DbA0         }          注意上面在拼接输出文件的绝对路径的时候,文件名不要用upload.get(i).getName()!          通过遍历用户的上传文件数目一个一个上传。         public String execute() throws Exception {中文JAVA技术网SZ(HChT+s         for(int i=0;i中文JAVA技术网1dL0Lzn:ff,M        /upload &])x"^_1Z8O,xO0       /success.jsp中文JAVA技术网j wTH/j%D(R1}`        /index.jsp         在配置文件中通过DI来注入值,这样可以增强程序的灵活性!这里要提醒大家的是最好为action提供input视图, 因为在很多情况下struts会默认找input视图,比如:校验、上传等!        此时你会看到你的上传文件后在服务器的日志中打印没有临时目录的消息,所以这里要设置        常量,或者在struts.propertes或者 在web.xml中!仔细的人会发现临时目录是有struts维护的。         如何使用限制上传文件的大小和类型呢?  最佳的答案 文件上传拦截器(FileUploadInterceptor)         查看该拦截器的源代码片段如下:         protected Long maximumSize;          // 文件的最大值 yv\z0f zE;s0        protected Set allowedTypesSet = Collections.emptySet();  // 接受文件的类型         所以这里可以给上传的action提供参数,来DI相关的参数!具体如下配置:         中文JAVA技术网,r jw S8?4p         image/jpg,image/JPEG中文JAVA技术网R6\3?3q'a5f:l         2000中文JAVA技术网NhA#J2w|,L3O\         *[5?OA%w*mv*c;W`0                这里我说过一旦我们的action显式的配置了拦截器,那么strtus的拦截器就无效了,所以我们还有手工添加struts的默认拦截器栈,聪明的你估计会问默认的拦截器栈里面不是有这个拦截器吗?我们为什么还要自己配置呢?         呵呵! 问的好,这里配置是为了个拦截器加参数,如果开发人员配置的拦截器是struts默认拦截器有的,这里struts框架自己会判断该拦截器是否已经执行了,如果执行了,相同的拦截器就不会再次执行!        这里还要说明2点:        1、allowedTypes这个参数接受的是文件的MIME类型,不清楚的人可查看相关文档,这里笔者就不列举了!        2、maximumSize单位是字节         此时的文件上传已经好了,但是当你上传的文件过大、或者没有在允许的范围内的话,会出现一些显眼的英文,这就又涉及到了struts2的国际化了,查看struts-messages.properties文件,根据错误消息找到对应的消息的key值,开发人员自己建立资源文件加载其中的中文字段就OK啦!         通过上述大家已经可以掌握struts2的文件上传了,接下来我们讲解下下载:         其实如果说文件上传是文件的复制(输入--》输出)的话,那么文件的下载就是文件的输出,所以当用户下载文件的 时候从技术角度看,就是一个文件的输出流在通过缓存输出文件! 难道不是吗? 呵呵        但是这里大家要注意的是strus2帮我们提供好了输出流,所以在下载的时候我们要给输出流提供一个输入流!        既然是一个输入流那么就要考虑2个问题:       1、文件位置+文件名       2、文件流的获取+返回       下载文件的action:DownloadAction.java       public InputStream getDownloadFile() {   中文JAVA技术网laglx#S*L9W       return     ServletActionContext.getServletContext().getResourceAsStream(path+fileName);   中文JAVA技术网:O&W'UjK-}j/?.b       }        // path和fileName可以写死在程序中(硬编码)、或者注入进来(配置action时采用param)、请求参数传递过来       中文JAVA技术网j*Zz` ZiJ W!K-[           WCs4q)Ro0                   中文JAVA技术网iS9G6NR;y5`              text/plain   中文JAVA技术网vT&]dz.s|A0r.Q                    中文JAVA技术网m#Y`z5gf                 中文JAVA技术网/Fs"k+Ro"Nmn.h+S J @xm                     attachment;filename="jiao.txt"   |H0qL9n8bI%m0                   +C/G [C.j f.` qZ0                   中文JAVA技术网.l'cO&]8|o;U7W                 downloadFile 中文JAVA技术网4`Z'[4IBK\2`                   中文JAVA技术网q)m wxL:_K:g\               contentType:下载文件的内容类型!        contentDisposition:通知浏览器对于该文件的处理方式,默认是inline的,也就是在页面试图打开文件,这里采用附件的形式,通知浏览器给客户端提供一个保存窗口来另存为文件!        inputName:告诉struts action中的哪个方法给输出流提供输入流。        这里的三个参数没有必要记忆,大家可以参考stream对应的Result查看源代码:                 protected String contentType = "text/plain"; x"DDM.E-SBz0        protected String contentLength;中文JAVA技术网 ~%ULe)Ay"iK         protected String contentDisposition = "inline"; :U(ad \K@?v9ZF k0        protected String contentCharSet ; HH'qa.^6b.p]"Y0        protected String inputName = "inputStream";中文JAVA技术网V5Ax E&U Dh         protected InputStream inputStream; +{~ ^GZ? l0        protected int bufferSize = 1024;中文JAVA技术网5{(M {)m-EvhX:ju         protected boolean allowCaching = true;          此时大家就可以看到这些参数的默认值都是什么了!呵呵,这就是学习开源技术的一种手法,现在市场上的SSH书那么贵,对于学习者而言官方文档是最好的选择、也是最佳的选择!         不知道很多人都会遇到乱码问题,这里笔者告诉大家一个屡试不爽的方法:        1、和struts2保持统一的编码方式(默认是UTF-8)        2、获取用户的文件名后new String(name.getBytes("ISO-8859-1"),UTF-8);        到此struts2的文件上传和下载就讲完了,呵呵,写这个只是为了方便大家学习,有错误之处请不吝赐教,也希望大家提宝贵意见,如果是高手请路过! 呵呵......闲暇之余随笔........          教学反馈:         学完了文件的上传和下载,struts2的基本知识和核心的知识基本就告一段落了,呵呵,今天学生在实验的时候遇到一个问题,问题描述:文件上传可以,而且上传的目录中可以正常显示中文的文件,但是在下载中文文件的时候遇到一个无效参数的问题: java.lang.IllegalArgumentException: Can not find a java.io.InputStream with the name [downloadFile] in the invocation stack. Check the tag specified for this action. 此时可以从错误中分析是由于下载时候的编码和中文冲突的问题! 这里要采用的是告诉浏览器在URL编码的时候如何编码,记得一般我们在配置Tomcat的时候都是会去配置两个文件:        Tomcat的安装目录下的conf:server.xml和context.xml文件要添加如下的信息:        server.xml:                          这样使用URL编码是就会采用UTF-8的编码方式了!         当然了,对于实验的时候大家可能都采用的是Myeclipse自带的tomcat所以这里大家要去寻找自带的tomcat所在的路径,找到conf的配置文件,然后如上配置就OK啦,呵呵,感谢这位学生提出的问题!         教学反馈2:         在学生的上机实验中有同学想把上传的文件放在项目的根目录下,这个时候问我路径要怎么写?        解决方案:        上传的时候提供"/"路径为保存路径,同时在下载的时候也要设置相同的路径!这里推荐大家还是要把上传的文件统一按类放在不同的文件目录中,1、便于管理  2、便于下载 。还有就是有些人采用的是IE8的话文件在上传的时候 默认会改变路径,所以大家要去在IE的选项中设置安全级别,详细见邮件开发的文章! 还有就是大家对于上传文件目录的建立可以直接在Web-Root目录下创建一个文件目录,发布后会自动发布到服务器端!         教学反馈3:         关于下载的时候使用迅雷下载的话会出现处理的对应的action的名字,如何使得该名字为下载文件的名字?         解决方案:         这个与迅雷的设计有关系, 这里大家可以下载下文件后看到是否是你要的文件名,如果是就ok了! 利用Struts2的Stream结果类型进行文件下载 Struts 2010-09-04 02:34:55 阅读347 评论0  字号:大中小 订阅 文件的下载,需要利用到struts2的Stream结果类型: 首先来看Struts2的返回类型(来自官网).Stream是用来把一个输入流返回到浏览器,这个就是用来文件下载的 Chain Result Used for Action Chaining Dispatcher Result Used for web resource integration, including JSP integration FreeMarker Result Used for FreeMarker integration HttpHeader Result Used to control special HTTP behaviors Redirect Result Used to redirect to another URL (web resource) Redirect Action Result Used to redirect to another action mapping Stream Result Used to stream an InputStream back to the browser (usually for file downloads) Velocity Result Used for Velocity integration XSL Result Used for XML/XSLT integration PlainText Result Used to display the raw content of a particular page (i.e jsp, HTML) Tiles Result Used to provide Tiles integration     Stream结果类的参数(来自官网): · contentType - the stream mime-type as sent to the web browser (default = text/plain).                             MIME类型(默认是 text / plain)。用来设置HTTP响应里的Content-Type标头 · contentLength - the stream length in bytes (the browser displays a progress bar). 字节流的长度(浏览器显示一个进度栏)。用来设置HTTP响应里的Content-Length标头 · contentDisposition - the content disposition header value for specifing the file name (default = inline, values are typically attachment;filename="document.pdf". 设置标题为什么文件名(规定文件名=“document.pdf”) 用来设置HTTP响应里的Content-Disposition标头 · inputName - the name of the InputStream property from the chained action (default = inputStream). 一个动作类属性的名字,此属性返回的InputStream对象会被发送到浏览器 · bufferSize - the size of the buffer to copy from input to output (default = 1024). 缓冲区大小(默认= 1024,单位是字节)。通过InputStream对象读取数据,通过OutputStream对象向浏览器发送数据时的缓冲区的长度 · allowCaching if set to 'false' it will set the headers 'Pragma' and 'Cache-Control' to 'no-cahce', and prevent client from caching the content. (default = true)  如果设置为false,它将设置标题语无缓存,防止客户端从缓存读取内容。 (默认= true) · contentCharSet if set to a string, ';charset=value' will be added to the content-type header, where value is the string set. If set to an expression, the result of evaluating the expression will be used. If not set, then no charset will be set on the header 如果设置为一个字符串, charset为设置的字符串,如果没有设置,然后将头没有字符集的设置   e.g: struts.xml文件内容                                                                              inputStream               text/css               filename="main.css"               2048                                                              inputStream               application/octet-stream               filename="main.css"               2048                              注意:这两个action的区别就是它们的contentType被设置成不同的值,ViewCss是把文件内容发送到浏览器,DownloacCss是下载文件.       Download.java内容 实现了ServletContextAware接口 package com.download.action;   import java.io.InputStream;   import javax.servlet.ServletContext;   import org.apache.struts2.util.ServletContextAware;   import com.opensymphony.xwork2.ActionSupport;   public class Download extends ActionSupport implements ServletContextAware{         private String filePath;     private ServletContext servletContext;         public void setServletContext(ServletContext servletContext) {         this.servletContext = servletContext;     }     public void setFilePath(String filePath) {         this.filePath = filePath;     }     public InputStream getInputStream() throws Exception {         return servletContext.getResourceAsStream(filePath);     }   }       index.jsp内容 <%@ page language="java" import="java.util.*" pageEncoding="utf-8"%> <%@ taglib prefix="s" uri="/struts-tags"%>               Download        @import url(css/main.css);                                               css/main.css                        View CSS                                         css/main.css                        Download CSS        
    

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 15 金币 [ 分享文档获得金币 ] 3 人已下载

下载文档