Struts2提供FileUpload拦截器和Jakarta Commons FileUpload组件以实现文件的上传功能,即需要导入commons-fileupload-1.3.jar与commons-io-2.0.1.jar依赖包。
一、文件的上传
1.1 表单准备
要想使用HTML表单上传一个或多个文件,则需要:
- 将表单的method属性设置为post;
- 将表单的enctype属性设置为multipart/form-data;
- 添加
<input type="file">
字段或使用s:file标签。
1.2 实现步骤
第一步:使用s:file标签,若需上传多个文件则使用多个s:file标签,并确保其name属性值一致;核心示例代码如下所示:
<s:form action="testUpload" enctype="Multipart/form-data" method="post">
<s:file name="ppt" label="PptFile"></s:file>
<s:textfield name="pptDesc" label="PptDesc"></s:textfield>
<s:submit></s:submit>
</s:form>
第二步:在对应Action类中定义与文件上传相关的三个基本属性,提供其getter()和setter()方法;三个基本属性分别是:
private File [fileFieldName]; // 被上传的文件所对应的File对象
private String [fileFieldName]ContentType; // 文件类型
private String [fileFieldName]FileName; // 文件名
第三步:使用IO流进行文件的上传即可。核心示例代码如下所示:
/**
* 利用IO流实现文件的上传
* 1). 获取服务器的文件存放路径
* 2). 准备输入流、输出流
* 3). 进行文件上传
* 4). 关闭输出流、输入流
*/
ServletContext context = ServletActionContext.getServletContext();
String realPath = context.getRealPath("/files/" + pptFileName);
System.out.println(realPath);
FileOutputStream out = new FileOutputStream(realPath);
FileInputStream in = new FileInputStream(ppt);
int len = 0;
byte[] buffer = new byte[1024];
while((len = in.read(buffer)) != -1) {
out.write(buffer, 0, len);
}
注意:如何实现一次性上传多个文件?将上述属性改为List类型,且需保证多个文件域的name属性值一致,但要特别注意文件描述字段的回显问题。
1.3 配置FileUpload拦截器
可以通过配置FileUploadInterceptor 拦截器参数的方式来限制上传文件的大小、类型和扩展名。可配置参数如下所示:
- maximumSize (optional):单个上传文件的最大值,默认为2M;
- allowedTypes (optional):所允许上传文件的类型,多个类型间用“,”隔开;
- allowedExtensions (optional):所允许上传文件的扩展名,多个扩展名间用“,”隔开;
拦截器配置示例如下所示:
<!-- 配置FileUpload拦截器:限制上传文件的大小、类型和扩展名 -->
<interceptors>
<interceptor-stack name="uploadControlStack">
<interceptor-ref name="defaultStack">
<param name="fileUpload.maximumSize">4000</param>
<param name="fileUpload.allowedTypes">text/html,text/xml</param>
<param name="fileUpload.allowedExtensions">html,xml</param>
</interceptor-ref>
</interceptor-stack>
</interceptors>
<default-interceptor-ref name="uploadControlStack"></default-interceptor-ref>
注意:在org.apache.struts2下的default.properties属性文件中对上传文件总大小进行了限制,可以使用常量的方式来修改该限制。
1.4 定制错误消息
可以在国际化资源文件中定义如下消息:
- struts.messages.error.uploading:文件上传出错的消息;
- struts.messages.error.file.too.large:文件大小超出最大值的消息;
- struts.messages.error.content.type.not.allowed:文件类型不合法的消息;
- struts.messages.error.file.extension.not.allowed:文件扩展名不合法的消息
注意:此种方式定制的消息并不完善,具体可参考org.apache.struts2下struts-messages.properties属性文件, 以提供合理完善的错误消息。
二、文件的下载
在某些应用程序里, 可能需要动态地将一个文件发送到用户的浏览器中,而该文件名和存放路径在编程时时无法预知的,如导出数据表等。而Struts专门为文件下载提供了一种Stream结果类型,在使用一个Stream结果时,不必准备一个JSP页面。
2.1 具体实现
- Struts2中使用type=”stream”的result进行下载;
- 具体使用细节参看struts-2.3.15.3-all/struts-2.3.15.3/docs/WW/docs/stream-result.html。
<action name="testDownload" class="com.qiaobc.struts.action.DownloadAction"
method="execute">
<result type="stream">
<!--静态指定属性值-->
<param name="bufferSize">2048</param>
</result>
</action>
2.2 参数配置
可以为type=”stream”的result设定如下参数:
- contentType:结果类型;
- contentLength:所下载文件的长度;
- contentDisposition:设定Content-Dispositoin响应头,指定响应为文件下载类型,通常设置为
attachment;filename=document.pdf
; - inputName:指定Action类中提供的文件输入流的getter对应的属性名,默认为inputStream;
- bufferSize:缓存区大小,默认为1024;
- allowCaching:是否允许使用缓存,默认为true;
- contentCharSet:指定下载的字符集。
注意:以上参数可以在Action类中以getter()方法的方式提供。
// 文件下载对应的Action类
package com.qiaobc.struts.action;
import java.io.FileInputStream;
import java.io.InputStream;
import javax.servlet.ServletContext;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownloadAction extends ActionSupport {
private static final long serialVersionUID = 1L;
private String contentType;
private long contentLength;
private String contentDisposition;
private InputStream inputStream;
public String getContentType() {
return contentType;
}
public long getContentLength() {
return contentLength;
}
public String getContentDisposition() {
return contentDisposition;
}
public InputStream getInputStream() {
return inputStream;
}
@Override
public String execute() throws Exception {
// 确定各个成员变量的值
contentType = "text/html";
contentDisposition = "attachment;filename=action-download.html";
ServletContext context = ServletActionContext.getServletContext();
String fileName = context.getRealPath("/files/action.html");
inputStream = new FileInputStream(fileName);
contentLength = inputStream.available();
return super.execute();
}