在做B/S系统时,通常会触及到上传文件和下载文件,在没接struts2框架之前,我们都是使用apache下面的commons子项目的FileUpload组件来进行文件的上传,但是那样做的话,代码看起来比较繁琐,而且不灵活,在学习了struts2后,struts2为文件上传下载提供了更好的实现机制,在这里我分别就单文件上传和多文件上传的实现进行1下讲授,这里
我们使用的struts2 web项目所导入的jar包中的**commons-fileupload⑴.3.1.jar
commons-io⑵.2.jar**是struts2实现上传下载所使用的类库
jsp页面表单的书写格式
<form name="myForm" enctype="multipart/form-data">
<input type="file" name="myDoc" value="Browse ..." />
<input type="submit" />
</form>
public void setMyDoc(File myDoc)
public void setMyDocContentType(String contentType)
public void setMyDocFileName(String filename)
public File getMyDoc()
public String getMyDocContentType()
public String getMyDocFileName()
首先是1个jsp文件上传页面,这个比较简单,就是1个表单,里面有个文件上传框
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>Insert title here</title>
</head>
<body>
<!--在进行文件上传时,表单提交方式1定要是post的方式,由于文件上传时2进制文件可能会很大,还有就是enctype属性,这个属性1定要写成multipart/form-data,
不然就会以2进制文本上传到服务器端-->
<form action="upload" method="post" enctype="multipart/form-data">
上传文件:<input name="photo" type="file"><br>
<input type="submit">
</form>
</body>
</html>
接下来是FileUploadAction部份代码,由于struts2对上传和下载都提供了很好的实习机制,所以在action这段我们只需要写很少的代码就行:
FileUploadAction.java
package com.lgh.struts2.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import sun.nio.ch.IOUtil;
public class FileUploadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private File photo;
private String photoContentType;
private String photoFileName;
@Override
public String execute() throws Exception {
InputStream is = new FileInputStream(photo);
String path = ServletActionContext.getServletContext().getRealPath("/upload");
String ext = photoFileName.substring(photoFileName.lastIndexOf(".")+1);
System.out.println(ext);
String filePath = path+"/"+UUID.randomUUID()+"."+ext;
OutputStream os = new FileOutputStream(filePath);
System.out.println(path);
IOUtils.copy(is, os);
os.close();
is.close();
return super.execute();
}
public File getPhoto() {
return photo;
}
public void setPhoto(File photo) {
this.photo = photo;
}
public String getPhotoContentType() {
return photoContentType;
}
public void setPhotoContentType(String photoContentType) {
this.photoContentType = photoContentType;
}
public String getPhotoFileName() {
return photoFileName;
}
public void setPhotoFileName(String photoFileName) {
this.photoFileName = photoFileName;
}
}
上传成功的页面
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>Insert title here</title>
</head>
<body>
<s:debug></s:debug>
</body>
</html>
action配置
<action name="upload*" class="com.lgh.struts2.action.FileUpload{1}Action"
method="execute">
<result name="success">/upload_sucess.jsp</result>
</action>
测试
提交落后入上传文件夹中:
当通过1个表单上传多个文件, 文件用数组来表示.
给定:
<form name="myForm" enctype="multipart/form-data">
<input type="file" name="myDoc" value="Browse File A ..." />
<input type="file" name="myDoc" value="Browse File B ..." />
<input type="file" name="myDoc" value="Browse File C ..." />
<input type="submit" />
</form>
Action 类定义了文件处理方法,这些方法接收数组参数.
public void setMyDoc(File[] myDocs)
public void setMyDocContentType(String[] contentTypes)
public void setMyDocFileName(String[] fileNames)
通过迭代数组来处理多个文件上传.
fileuploadMuti.jsp
<%@ page language="java" contentType="text/html; charset=UTF⑻"
pageEncoding="UTF⑻"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF⑻">
<title>Insert title here</title>
</head>
<body>
<form action="uploadMuti" method="post" enctype="multipart/form-data">
上传文件:<input name="photo" type="file"><br>
上传文件:<input name="photo" type="file"><br>
<input type="submit">
</form>
</body>
</html>
FileUploadMutiAction.java
package com.lgh.struts2.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.UUID;
import org.apache.commons.io.IOUtils;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
import sun.nio.ch.IOUtil;
public class FileUploadMutiAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private File[] photo;
private String[] photoContentType;
private String[] photoFileName;
@Override
public String execute() throws Exception {
for (int i = 0; i < photo.length; i++) {
InputStream is = new FileInputStream(photo[i]);
String path = ServletActionContext.getServletContext().getRealPath("/upload");
String ext = photoFileName[i].substring(photoFileName[i].lastIndexOf(".")+1);
System.out.println(ext);
String filePath = path+"/"+UUID.randomUUID()+"."+ext;
OutputStream os = new FileOutputStream(filePath);
System.out.println(path);
IOUtils.copy(is, os);
os.close();
is.close();
}
return super.execute();
}
public File[] getPhoto() {
return photo;
}
public void setPhoto(File[] photo) {
this.photo = photo;
}
public String[] getPhotoContentType() {
return photoContentType;
}
public void setPhotoContentType(String[] photoContentType) {
this.photoContentType = photoContentType;
}
public String[] getPhotoFileName() {
return photoFileName;
}
public void setPhotoFileName(String[] photoFileName) {
this.photoFileName = photoFileName;
}
}
action配置:
<action name="upload*" class="com.lgh.struts2.action.FileUpload{1}Action"
method="execute">
<result name="success">/upload_sucess.jsp</result>
</action>
测试:
提交后
属性 默许值
struts.multipart.parser 使用Commons FileUpload 框架
struts.multipart.saveDir 容器定义的javax.servlet.context.tempdir
设置上传文件的最大值
struts.multipart.maxSize 大约2M
文件上传后我们还需要将其下载下来,其实struts2的文件下载原理很简单,就是定义1个输入流,然后将文件写到输入流里面就行,关键配置还是在struts.xml这个配置文件里配置以下参数:
contentType - 告知阅读器的流的 mime-type (默许 = text/plain).
contentLength - 按字节计算的流长度(阅读器显示进度条).
contentDisposition -内容的 disposition 头值来指定文件的名称 (默许 = inline, 值通常是 attachment;filename=”document.pdf”.
inputName - the name of the InputStream property from the chained action (默许 = inputStream).
bufferSize - 从输入往输出拷贝时缓存的大小 (默许 = 1024).
allowCaching -如果设置为 ‘false’ 将设置头 ‘Pragma’ 和 ‘Cache-Control’为’no-cahce’, 并禁止客户端缓存该内容. (默许= true)
contentCharSet -如果设置为字符串, ‘;charset=value’ 将添加到 content-type 头. 如果为1个表达式, 将使用计算的结果. 如果没有设置, 将不添加字符编码到头
这些参数通过提供与参数名字相同的 getter 方法来设置到你的 Action. 例如, 你可以提供1个 getContentType() 方法来覆盖当前action的参数.
准备的文件:
文件下载不需要jsp页面,我们先配置action,这类方式是把下载文件写死的方式,不可用任意下载:
<action name="download" class="com.lgh.struts2.action.FileDownloadAction"
method="execute">
<result name="success" type="stream">
<param name="contentType">image/jpeg</param>
<param name="inputName">is</param>
<param name="contentDisposition">attachment;filename="123.jpg"</param>
<param name="bufferSize">1024</param>
</result>
</action>
action类:
FileDownloadAction.java
package com.lgh.struts2.action;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileDownloadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
public InputStream getIs() throws FileNotFoundException{
//文件下载时我们需要1个输入流来读取文件,其他的输出struts2会帮我们创建
return new FileInputStream(ServletActionContext.
getServletContext().getRealPath("/download")+"/123.jpg");
}
}
测试:
经测试下载成功
有时候我们的下载其实不固定格式,比如txt和jpg是两种不同的格式,123.txt和456.txt下载文件的名字也不相同,这时候我们的struts2.xml中的action配置就不能写死了,我们需要使它能根据传递过来的文件名不同动态的生成1些配置参数的值:
比如:通过OGNL表达式从文件下载action类中通过get方法得到值
<action name="downloadX" class="com.lgh.struts2.action.FileDownloadXAction"
method="execute">
<result name="success" type="stream">
<param name="contentType">${contentType}</param>
<param name="inputName">is</param>
<param name="contentDisposition">attachment;filename="${f}"</param>
<param name="bufferSize">1024</param>
</result>
</action>
这时候我们就要在相应的action类中创建get方法了
FileDownloadXAction.java
package com.lgh.struts2.action;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileDownloadXAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String f;
private String contentType;
public InputStream getIs() throws FileNotFoundException{
System.out.println(ServletActionContext.getServletContext().getMimeType(f));
return new FileInputStream(ServletActionContext.
getServletContext().getRealPath("/download")+"/"+f);
}
public String getF() throws UnsupportedEncodingException {
return f;
}
public void setF(String f) {
/*
* 在 tomcat7 中从get要求获得参数是若包括中文,
* 则会发现中文乱码现象
* 由于阅读器传送来的数据是以utf⑻编码的,在服务器tomcat则以iso⑻859⑴解码
* 产生了乱码,下面代码可以解决该问题
* new String(f.getBytes("ISO⑻859⑴"),"UTF⑻");
* */
this.f = f;
}
public String getContentType() {
System.out.println(f);
System.out.println(ServletActionContext.getServletContext().getMimeType(f));
return ServletActionContext.getServletContext().getMimeType(f);
}
}
测试
下载文件名非中文的
成功没有问题
下载中文名字文件
火狐阅读器:
谷歌阅读器:
我们看到在下载中文的文件时,文件名都出现了毛病
这是由于:阅读器在响应头中不允许中文存在 我们下载时必须content-disposition头中设置1些下载信息这时候如果我们要下载的文件包括中文,那末我们就必须进行编码
修改getF()方法:
public String getF() throws UnsupportedEncodingException {
/*
* 阅读器在响应头中不允许中文存在
* 我们下载时必须在content-disposition头中设置1些下载信息
* 这时候如果我们要下载的文件包括中文,那末我们就必须进行编码
*设置 URLEncoder.encode(name, "utf⑻") 对ie 谷歌 已可以了,
*但是对火狐依然有1些问题
*;filename*=utf-8''"+ URLEncoder.encode(name, "utf-8")
*用于就解决火狐阅读器的问题
*我们在struts2.xml通过配置的方式也能够到达以下功能
*
*/
/*
* 这时候我们不使用struts2框架下载时所需要设置的响应头
* response.setHeader("content-disposition", "attachment;filename=\""+
URLEncoder.encode(name, "utf⑻")+"\";filename*=utf⑻''"+
URLEncoder.encode(name, "utf⑻"));
* */
return URLEncoder.encode(f, "utf⑻");
}
测试:
火狐阅读器测试:
解决
但是对火狐依然有1些问题
不使用框架则以下代码 用于就解决火狐阅读器的问题
;filename*=utf⑻””+ URLEncoder.encode(name, “utf⑻”)
我们在struts2.xml通过配置的方式也能够到达以下功能
这时候问题解决了:
总的来讲,struts2提供的文件上传下载机制简化了我们很多代码,我们可以在以后的项目中使用该机制,一样我们也能够使用FileUpload组件来进行文件的上传,这个都是因个人爱好决定!