上篇文章又一次回顾了Struts2的运行机制,对它的运行步骤做了一步步的解析,这个解析不但再一次理清了Struts2的使用方法,而且对它的映射机制进行了深入的解析,并在最后通过一个实例来介绍了Struts2的一种使用方法,这里将做一个有关文件上传下载的实例。
一、文件上传
Struts2并没有提供文件上传的组件,所以想要实现上传的功能就必须通过第三方组件来实现,在Struts2引用的jar中包含了文件上传的组件,它是通过commons-fileupload.jar和commons-io.jar来实现的。这其中的处理细节不需要太懂,在使用中慢慢思考就可以做到灵活运用。
1、首先编写Action类
该类名称为downloadAction.java,必须在该类中引入java.io,文件上传的核心实现使用的还是java的数据流io操作。
- package com.action;
- import java.io.File;
- import java.io.FileInputStream;
- import java.io.FileOutputStream;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- public class uploadAction extends ActionSupport {
- private File file;
- 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;
- }
- //文件名称
- private String fileFileName;
- //文件类型
- private String fileContentType;
- //注意:文件名称和文件类型的名称前缀必须相同,
- @Override
- public String execute() throws Exception{
- //获取需要上传文件的文件路径
- File uploadFile=new File(ServletActionContext.getServletContext().getRealPath("uploadFile"));
- //判断文件是否上传,如果上传的话将会创建该目录
- if(!uploadFile.exists()){
- uploadFile.mkdir(); //创建该目录
- }
- //第一种文件上传的方法
- //声明文件输入流,为输入流指定文件路径
- FileInputStream input=new FileInputStream(file);
- //获取输出流,获取文件的文件地址及名称
- FileOutputStream out=new FileOutputStream(uploadFile + "\\" +fileFileName);
- try{
- byte[] b=new byte[1024];//每次写入的大小
- int i=0;
- while((i=input.read(b))>0){
- out.write(b,0,i);
- }
- }catch(Exception e){
- e.printStackTrace();
- }finally{
- input.close();
- out.close();
- }
- //第二种文件上传的方法
- //FileUtils.copyFile(upload,new File(uploadFile+"\\"+uploadFileName));
- //FileUtils.copyFile(upload,new File(uploadFile,uploadFileName));
- //第三种方法
- // BufferedReader bReader=new BufferedReader(new InputStreamReader(new FileInputStream(upload)));
- // BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(uploadFile+"\\"+uploadFileName)));
- // try{
- // char[] str=new char[1024];
- // int i=0;
- // while((i=bReader.read(str))>0){
- // bWriter.write(str,0,i);
- // }
- // }catch(Exception e){
- // e.printStackTrace();
- // }finally{
- // bReader.close();
- // bWriter.close();
- // uploadFile.delete();
- // }
- return "success";
- }
- }
package com.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class uploadAction extends ActionSupport {
private File file;
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;
}
//文件名称
private String fileFileName;
//文件类型
private String fileContentType;
//注意:文件名称和文件类型的名称前缀必须相同,
@Override
public String execute() throws Exception{
//获取需要上传文件的文件路径
File uploadFile=new File(ServletActionContext.getServletContext().getRealPath("uploadFile"));
//判断文件是否上传,如果上传的话将会创建该目录
if(!uploadFile.exists()){
uploadFile.mkdir(); //创建该目录
}
//第一种文件上传的方法
//声明文件输入流,为输入流指定文件路径
FileInputStream input=new FileInputStream(file);
//获取输出流,获取文件的文件地址及名称
FileOutputStream out=new FileOutputStream(uploadFile + "\\" +fileFileName);
try{
byte[] b=new byte[1024];//每次写入的大小
int i=0;
while((i=input.read(b))>0){
out.write(b,0,i);
}
}catch(Exception e){
e.printStackTrace();
}finally{
input.close();
out.close();
}
//第二种文件上传的方法
//FileUtils.copyFile(upload,new File(uploadFile+"\\"+uploadFileName));
//FileUtils.copyFile(upload,new File(uploadFile,uploadFileName));
//第三种方法
// BufferedReader bReader=new BufferedReader(new InputStreamReader(new FileInputStream(upload)));
// BufferedWriter bWriter=new BufferedWriter(new OutputStreamWriter(new FileOutputStream(uploadFile+"\\"+uploadFileName)));
// try{
// char[] str=new char[1024];
// int i=0;
// while((i=bReader.read(str))>0){
// bWriter.write(str,0,i);
// }
// }catch(Exception e){
// e.printStackTrace();
// }finally{
// bReader.close();
// bWriter.close();
// uploadFile.delete();
// }
return "success";
}
}
Action类中需要注意的是 文件名和文件类型的命名都是有要求的,文件名和文件类型的前缀必须是文件变量,并且要和jsp页面中添加的文件名称一致,如上例中的jsp标签为:<input type='File' name='file'>,在Action类中的文件名称和文件类型必须相应为fileXXX和fileXXX。另外也可以在该Action类中配置其它上传属性,如:可以通过maximumSize指定上传文件的大小,allowedTypes执行上传文件的类型。
上面的Action类指定了三种上传方法,它们操作的核心还是java.io,通过数据流的读入和写出来实现文件的上传。其中第一种和第三种采用的是java.io流操作,而第二种采用的是common.io流操作。
2、struts2.xml相应的action配置
action类编写完成后,接下来要把它配置到相应的action标签中,这样在执行action时会根据注册类执行内部的方法。具体配置方法如下实例。
- <package name="upload" namespace="/file" extends="struts-default">
- <action name="upload" class="uploadAction">
- <result name="success">/success.jsp</result>
- <result name="error">/error.jsp</result>
- <result name="input">/index.jsp</result>
- <param name="savePath">/upload</param>
- </action>
- </package>
<package name="upload" namespace="/file" extends="struts-default">
<action name="upload" class="uploadAction">
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
<result name="input">/index.jsp</result>
<param name="savePath">/upload</param>
</action>
</package>
3、最后配置相应的jsp页面
在配置时需要注意的是文件的编码格式,需要改成multipart/form-data类型,是指把文件及文件的内容都提交,另外enctype还有两个属性值分别是text/plain,指定了表单是以文本的方式进行提交;application/x-www-form-urlencoded这是默认的编码方式,提交时,只提交表单域的value属性值。
- <body>
- <form action="file/upload" method="post" enctype="multipart/form-data">
- <input type="file" name="upload">
- <input type="submit" name="btnUpload" value="上传">
- </form>
- </body>
<body>
<form action="file/upload" method="post" enctype="multipart/form-data">
<input type="file" name="upload">
<input type="submit" name="btnUpload" value="上传">
</form>
</body>
最后提交,查看提交结果,提交后的文件默认存放在.metadata\.plugins\org.eclipse.wst.server.core\tmp0\wtpwebapps\项目名称\uploadFile下,所以在编写action类时需要获取文件上传的路径使用的是getRealPath("uploadFile")。
二、文件下载
相较上传,文件的下载编写起来相交就简单多了,首先也需要添加下载的action类,然后配置struts.xml中的action,最后在jsp中添加链接标签。
1、添加下载action类
添加的action类指定要注意获取文件的输出路径,通过获取输出流来获取文件的路径。
- package com.action;
- import java.io.InputStream;
- import org.apache.struts2.ServletActionContext;
- import com.opensymphony.xwork2.ActionSupport;
- public class downloadAction extends ActionSupport {
- private InputStream fileInput;
- private String fileName;
- public String getFileName() {
- return fileName;
- }
- public void setFileName(String fileName) {
- this.fileName = fileName;
- }
- public InputStream getFileInput() {
- return ServletActionContext.getServletContext().getResourceAsStream("upload\\"+fileName);
- }
- public void setFileInput(InputStream fileInput) {
- this.fileInput = fileInput;
- }
- public String execute() throws Exception{
- fileInput=ServletActionContext.getServletContext().getResourceAsStream("upload\\"+fileName);
- return "success";
- }
- }
package com.action;
import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class downloadAction extends ActionSupport {
private InputStream fileInput;
private String fileName;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public InputStream getFileInput() {
return ServletActionContext.getServletContext().getResourceAsStream("upload\\"+fileName);
}
public void setFileInput(InputStream fileInput) {
this.fileInput = fileInput;
}
public String execute() throws Exception{
fileInput=ServletActionContext.getServletContext().getResourceAsStream("upload\\"+fileName);
return "success";
}
}
2、配置struts.xml标签
在配置时结果类型要指定type类型,将它赋值为stream,并添加属性下面的属性,该属性同样可以配置到拦截器中,在拦截器中指定配置的文件。
- <action name="download" class="com.action.downloadAction">
- <result name="success" type="stream">
- <param name="inputName">fileInput</param>
- <param name="contentDispostion">attachment;filename="$(fileName)"</param>
- </result>
- </action>
<action name="download" class="com.action.downloadAction">
<result name="success" type="stream">
<param name="inputName">fileInput</param>
<param name="contentDispostion">attachment;filename="$(fileName)"</param>
</result>
</action>
3、jsp页面代码
jsp代码就很简单了,不多说看代码。
- <body>
- <a href="file/download">123.txt</a>
- </body>
<body>
<a href="file/download">123.txt</a>
</body>
结语
通过使用文件的上传下载功能来熟悉Struts2的使用方法,并了解Servlet请求的基本用法,为以后深入学习Servlet打下基础。struts的文件上传和下载使用的是io流操作完成的,可以使用java.io流,同样可以使用第三方的common.io流实现,有关多文件上传的问题将会在下篇文章中讨论。