1、struts2 的上传和下载博客分类: STRUTS2StrutsJavaApache 框架应用服务器 1. 文件上传的原理:表单元素的 enctype 属性指定的是表单数据的编码方式,该属性有 3 个值:1) application/x-www-form-urlencoded:这是默认编码方式,它只处理表单域里的 value 属性值,采用这种编码方式的表单会将表单域的值处理成 URL 编码方式。2) multipart/form-data:这种编码方式的表单会以二进制流的方式来处理表单数据,这种编码方式会把文件域指定文件的内容也封装到请求参数里。3) text/plain:这种方式主要适用于
2、直接通过表单发送邮件的方式。文件上传是 web 应用经常用到的一个知识。原理是,通过为表单元素设置enctype=”multipart/form-data”属性,让表单提交的数据以二进制编码的方式提交,在接收此请求的 Servlet 中用二进制流来获取内容,就可以取得上传文件的内容,从而实现文件的上传。在 Java 领域中,有两个常用的文件上传项目:一个是 Apache 组织 Jakarta 的Common-FileUpload 组件(http:/commons.apache.org/fileupload/),另一个是 Oreilly 组织的 COS 框架(http:/ Struts2 的文件
3、上传:Struts2 并未提供自己的请求解析器,也就是就 Struts2 不会自己去处理multipart/form-data 的请求,它需要调用其他请求解析器,将 HTTP 请求中的表单域解析出来。但 Struts2 在原有的上传解析器基础上做了进一步封装,更进一步简化了文件上传。Struts2 默认使用的是 Jakarta 的 Common-FileUpload 框架来上传文件,因此,要在 web 应用中增加两个 Jar 文件:commons-fileupload-1.2.jar 和 commons-io-1.3.1.jar。它在原上传框架上做了进一步封装,简化了文件上传的代码实现,取消了
4、不同上传框架上的编程差异。如果要改成其它的文件上传框架,可以修改 struts.multipart.parser 常量的值为 cos/pell,默认值是 jakata。并在 classpath 中增加相应上传组件的类库。2.1. 步骤一:创建带上传表单域的页面Java 代码 1. 2. 3. 4. Struts2 File Upload 5. 6. 7. 8. 文件标题: 9. 选择文件: 10. 11. 12. 13. 此页面特殊之处只是把表单的 enctype 属性设置为 multipart/form-data。2.2. 步骤二:创建处理上传请求的 Action 类Java 代码 1. i
5、mport java.io.BufferedInputStream; 2. import java.io.BufferedOutputStream; 3. import java.io.File; 4. import java.io.FileInputStream; 5. import java.io.FileOutputStream; 6. import java.io.InputStream; 7. import java.io.OutputStream; 8. import org.apache.struts2.ServletActionContext; 9. import com.op
6、ensymphony.xwork2.ActionSupport; 10./* 11.*处理文件上传的 Action 类 12.*skyqiang 13.*version1.0 14.*/ 15.publicclass FileUploadAction extends ActionSupport 16.privatestaticfinalintBUFFER_SIZE = 16 * 1024; 17./ 文件标题 18.private String title; 19./ 上传文件域对象 20.private File upload; 21./ 上传文件名 22.private String up
7、loadFileName; 23./ 上传文件类型 24.private String uploadContentType; 25./ 保存文件的目录路径(通过依赖注入) 26.private String savePath; 27./以下省略 getter 和 setter. 28./自己封装的一个把源文件对象复制成目标文件对象 29.privatestaticvoid copy(File src, File dst) 30.InputStream in = null; 31.OutputStream out = null; 32.try 33.in = new BufferedInputS
8、tream(new FileInputStream(src), BUFFER_SIZE); 34.out = new BufferedOutputStream(new FileOutputStream(dst), 35.BUFFER_SIZE); 36.byte buffer = newbyteBUFFER_SIZE; 37.int len = 0; 38.while (len = in.read(buffer) 0) 39.out.write(buffer, 0, len); 40. 41. catch (Exception e) 42.e.printStackTrace(); 43. fi
9、nally 44.if (null != in) 45.try 46.in.close(); 47. catch (IOException e) 48.e.printStackTrace(); 49. 50. 51.if (null != out) 52.try 53.out.close(); 54. catch (IOException e) 55.e.printStackTrace(); 56. 57. 58. 59. 60.Override 61.public String execute() throws Exception 62./根据服务器的文件保存地址和原文件名创建目录文件全路径
10、 63.String dstPath = ServletActionContext.getServletContext() 64.getRealPath(this.getSavePath() 65.+ “ + this.getUploadFileName(); 66.67.System.out.println(“上传的文件的类型:“+ this.getUploadContentType(); 68.69.File dstFile = new File(dstPath); 70.copy(this.upload, dstFile); 71.returnSUCCESS; 72. 73. 上面这个
11、Action 类中,提供了 title 和 upload 两个属性来分别对应页面的两个表单域属性,用来封装表单域的请求参数。但是,值得注意的是,此 Action 中还有两个属性:uploadFileName 和uploadContentType,这两个属性分别用于封装上传文件的文件名、文件类型。这是 Struts2 设计的独到之处:Strut2 的 Action 类直接通过 File 类型属性直接封装了上传文件的文件内容,但这个 File 属性无法获取上传文件的文件名和文件类型,所以 Struts2 就直接将文件域中包含的上传文件名和文件类型的信息封装到 uploadFileName 和 up
12、loadContentType 属性中,也就是说 Struts2 针对表单中名为 xxx 的文件域,在对应的 Action 类中使用 3 个属性来封装该文件域信息:l 类型为 File 的 xxx 属性:用来封装页面文件域对应的文件内容。l 类型为 String 的 xxxFileName 属性:用来封装该文件域对应的文件的文件名。l 类型为 String 的 xxxContentType 属性:用来封装该文件域应用的文件的文件类型。另外,在这个 Action 类中还有一个 savePath 属性,它的值是通过配置文件来动态设置的,这也是 Strut2 设计中的一个依赖注入特性的使用。2.3.
13、 步骤三:配置struts.xml 文件:Java 代码 1. 4. 5. 6. 7. 8. /upload 9. /showupload.jsp 10. 11. 12. 在这个文件中跟以前配置唯一不同的是给 action 配置了一个元素,用来为该 Action 的 savePath 属性动态注入值。web.xml 中的配置跟以前的应用一样。说明一点:好多网络文章说 Struts2 上传时要在 web.xml 中配置一个名为 ActionContextUp 的过滤器,说是有一些莫名的错误,可是是我用了 Struts2 新版本 2.0.9GA 版,测了 n 次,没出现什么问题,所以没配置。2.4
14、. 运行调试:运行前要在根目录下创建一个名为 upload 的文件夹,用来存放上传后的文件。上传结果:3. 文件类型及错误输出:Struts2 提供了一个文件上传的拦截器(名为 fileUpload),通过配置这个拦截器能轻松地实现文件类型的过滤。在上例中,若要配置上传的文件只能是一些普通的图片文件格式:image/bmp、image/png、image/gif、image/jpeg、image/jpg 等,则可在struts.xml 文件中按如下方式配置:Java 代码 1. 3. 4. 5. 6. 8. 9. 10. 11. image/bmp,image/png,image/gif,im
15、age/jpeg,image/jpg ,image/x-png, image/pjpeg 12. 13. 14.102400 15. 16. 17. 18./upload 19./index.jsp 20./showupload.jsp 21. 22. 23. 如果上传文件失败,系统返回到 input 对应的页面,要在 input 对应的页面输出文件过滤失败信息,可以在 input 对应的页面中增加 来显示错误信息。运行调试:结果:显然,这样的提示不太友好,应用使用国际化信息。在国际化资源文件中添加如下三句:#更改上传文件类型不允许的提示信息struts.messages.error.cont
16、ent.type.not.allowed=文件上传失败:你要上传的文件类型不允许#更改上传文件太大的提示信息struts.messages.error.file.too.large=文件上传失败:你要上传的文件太大#文件上传其它错误信息struts.messages.error.uploading=文件上传失败:发生内部错误 别忘了要用 native2ascii.exe 进行编码转换哦。再运行调试:另外,在控制台会看到一条消息:Unable to find struts.multipart.saveDir property setting. Defaulting to javax.servle
17、t.context.tempdirRemoving file upload D:tomcat6.0.13workCatalinalocalhostfileload_struts2upload_4b616fd1_115a3d5d9dc_7fff_00000005.tmp 第一个说是找不以 struts.multipart.saveDir,即没有指定临时文件夹,这个很好解决,只需指定一个 struts.multipart.saveDir 常量值为某个目录来解决。第二个说正在删除一个临时文件,这个临时文件是上传过程中产生的,属正常。4. 多文件上传:Struts2 也可以很方便地实现多文件上传。在输
18、入表单域增加多个文件域:multifileupload.jspJava 代码 1. 2. 3. 4. 5. 多文件上传 6. 7. 8. 9. 10.文件标题: 11. 12.选择第一个文件: 13.选择第二个文件: 14. 15. 16. 17. 18.19.在 Action 类中用数组来封装该多个文件域:MultiFileUploadAction.java 20.21.import java.io.BufferedInputStream; 22.import java.io.BufferedOutputStream; 23.import java.io.File; 24.import ja
19、va.io.FileInputStream; 25.import java.io.FileOutputStream; 26.import java.io.IOException; 27.import java.io.InputStream; 28.import java.io.OutputStream; 29.import org.apache.struts2.ServletActionContext; 30.import com.opensymphony.xwork2.ActionSupport; 31./* 32.*处理多文件上传的 Action 类 33.* 34.*skqyiang*v
20、ersion1.0 35.*/ 36.publicclass MultiFileUploadAction extends ActionSupport 37.privatestaticfinalintBUFFER_SIZE = 16 * 1024; 38./ 文件标题 39.private String title; 40./ 用 File 数组来封装多个上传文件域对象 41.private File upload; 42./ 用 String 数组来封装多个上传文件名 43.private String uploadFileName; 44./ 用 String 数组来封装多个上传文件类型 4
21、5.private String uploadContentType; 46./ 保存文件的目录路径(通过依赖注入) 47.private String savePath; 48./以下为所有属性的 getter 和 setter。省略。 49./ 自己封装的一个把源文件对象复制成目标文件对象 50.privatestaticvoid copy(File src, File dst) 51.InputStream in = null; 52.OutputStream out = null; 53.try 54.in = new BufferedInputStream(new FileInput
22、Stream(src), BUFFER_SIZE); 55.out = new BufferedOutputStream(new FileOutputStream(dst), 56.BUFFER_SIZE); 57.byte buffer = newbyteBUFFER_SIZE; 58.int len = 0; 59.while (len = in.read(buffer) 0) 60.out.write(buffer, 0, len); 61. 62. catch (Exception e) 63.e.printStackTrace(); 64. finally 65.if (null !
23、= in) 66.try 67.in.close(); 68. catch (IOException e) 69.e.printStackTrace(); 70. 71. 72.if (null != out) 73.try 74.out.close(); 75. catch (IOException e) 76.e.printStackTrace(); 77. 78. 79. 80. 81.Override 82.public String execute() throws Exception 83.File srcFiles = this.getUpload(); 84./ 处理每个要上传
24、的文件 85.for (int i = 0; i srcFiles.length; i+) 86./ 根据服务器的文件保存地址和原文件名创建目录文件全路径 87.String dstPath = ServletActionContext.getServletContext() 88.getRealPath(this.getSavePath() 89.+ “ + this.getUploadFileName()i; 90.File dstFile = new File(dstPath); 91.this.copy(srcFilesi, dstFile); 92. 93.returnSUCCESS; 94. 95. 运行结果:5. Struts2 的文件下载:文件下载相对简单一些,一般只需在页面上提供一个超链接,该链接的 href 属性等于要下载文件的文件名就行了。但当文件名有中文时,就会导致失败;或者要在用户下载前进行权限判断,这时用 Struts2 提供的文件下载功能就能简单的解决这些问题