时间:2017-1-11 15:47
——使用commons-fileupload组件上传
1、客户端
* method="post"
* <input type="file" name="xx" />
* encType="multipart/form-data"
2、服务器端
使用commons-fileupload。
* DiskFileItemFactory
* ServletFileUpload
* FileItem
——Struts2文件上传
默认情况下,Struts2框架使用commons-fileupload组件进行上传操作,所以需要导入commons-fileupload.jar。
Struts2使用了一个interceptor帮助我们完成文件上传操作:
<interceptor name="fileUpload" class="org.apache.struts2.interceptor.FileUploadInterceptor"/>
实现文件上传操作:
页面中:
<form action="${pageContext.request.contextPath }/upload" method="post" enctype="multipart/form-data">
<input type="file" name="file" />
<input type="submit" value="上传" />
</form>
如果要同时上传多个文件,那么所有"file"的name属性值必须相同。
Action中:
public class UploadAction extends ActionSupport {
/*
* 在Action类中需要声明三个属性
*/
private File file; // 上传文件,名称必须与表单页面中的name值相同
private String fileContentType; // 上传文件类型,名称格式:name + ContentType
private String fileFileName; // 上传文件名,名称格式:name + FileName
/*
* 在FileUploadInterceptor中有如下三行代码,所以起名必须要规范
* String inputName = (String) fileParameterNames.nextElement();
* String contentTypeName = inputName + "ContentType";
* String fileNameName = inputName + "FileName";
*/
@Override
public String execute() throws Exception {
System.out.println("上传文件的类型:" + fileContentType);
System.out.println("上传文件的名称:" + fileFileName);
// 完成文件上传
// 使用FileUtils的copyFile()方法将文件的输入流输出到指定位置
FileUtils.copyFile(file, new File("f:/upload", fileFileName));
return NONE;
}
public File getFile() {
return file;
}
public void setFile(File file) {
this.file = file;
}
public String getFileContentType() {
return fileContentType;
}
public void setFileContentType(String fileContentType) {
this.fileContentType = fileContentType;
}
public String getFileFileName() {
return fileFileName;
}
public void setFileFileName(String fileFileName) {
this.fileFileName = fileFileName;
}
}
——Struts2中文件上传细节
1、控制上传文件大小
在default.properties文件中定义了上传文件的大小:
struts.multipart.maxSize=2097152 上传文件大小默认2M
超出文件大小时,跳转到input视图,通过<s:actionerror />显示错误信息。
可以在struts.xml文件中重新定义常量来修改上传文件大小限制。
<constant name="struts.multipart.maxSize" value="86170804"/>
2、修改显示错误信息
默认在页面中显示的错误信息是英文的,可以在Struts2核心包下的struts-message.properties文件中找到预定义上传错误信息,在国际化文件中通过覆盖对应key显示错误信息:
// 上传错误:{0}
struts.messages.error.uploading=Error uploading: {0}
// 上传文件过大:{0} "{1}" "{2}" {3}
struts.messages.error.file.too.large=The file is to large to be uploaded: {0} "{1}" "{2}" {3}
// 上传文件不允许:{0} "{1}" "{2}" {3}
struts.messages.error.content.type.not.allowed=Content-Type not allowed: {0} "{1}" "{2}" {3}
// 上传文件扩展名不允许:{0} "{1}" "{2}" {3}
struts.messages.error.file.extension.not.allowed=File extension not allowed: {0} "{1}" "{2}" {3}
# dedicated messages used to handle various problems with file upload - check {@link JakartaMultiPartRequest#parse(HttpServletRequest, String)}
struts.messages.upload.error.SizeLimitExceededException=Request exceeded allowed size limit! Max size allowed is: {0} but request was: {1}!
struts.messages.upload.error.IOException=Error uploading: {0}!
{0}:<input type=“file” name=“uploadImage”>中name属性的值
{1}:上传文件的真实名称
{2}:上传文件保存到临时目录的名称
{3}:上传文件的类型(对struts.messages.error.file.too.large是上传文件的大小)
3、多文件上传时每个文件大小控制以及上传文件的扩展名限制
多文件上传时,要将Action中的属性声明为List集合或者数组:
private List<File> file;
private List<String> fileContentType;
private List<String> fileFileName;
然后在excuete()方法中进行操作。
怎样限制每一个上传文件的大小及其上传文件的类型?
在FileUploadInterceptor中有如下代码:
protected Long maximumSize; // 表示每个上传文件的大小
protected Set<String> allowedTypesSet = Collections.emptySet(); // 表示上传文件的类型
protected Set<String> allowedExtensionsSet = Collections.emptySet(); // 表示上传文件的扩展名
使用配置文件设置上传文件总大小,对所有上传form有效,如果只想对当前form进行设置,可以设置fileUplpad拦截器属性:
* maximumSize:上传文件的最大长度(以字节为单位),默认为2M。
* allowedTypes:允许上传的文件类型,各类型之间以逗号分隔。
* allowedExtendsions:允许上传文件扩展名,各扩展名之间以逗号分隔。
例如:
<action name="upload" class="com.wyc.action.UploadAction">
<interceptor-ref name="defaultStack">
<!-- 对fileUpload下的allowedExtension属性赋值 -->
<param name="fileUpload.allowedExtensions">txt,mp3,doc</param>
</interceptor-ref>
<result name="input">/upload.jsp</result>
</action>
如果针对fileUpload进行参数设置,当出错时,在页面通过<s:filedError />回显错误信息。
4、在Struts2中默认使用的是commons-fileupload进行文件上传
在default.properties文件中:
# struts.multipart.parser=cos
# struts.multipart.parser=pell
struts.multipart.parser=jakarta // jakarta表示apache开源项目
可以修改默认上传方式。
如果使用pell、cos进行文件上传,必须导入其jar包。
——文件下载
1、文件下载方式:
超链接
服务器编码,通过流向客户端写回。
下载的要求
两个头、一个流
* Content-Type:表示传递给客户端文件的MIME类型。
> 通过文件名称调用ServletContext的getMimeType()方法得到MIME类型。
* Content-Disposition:
> 它的默认值为inline,表示在浏览器窗口中打开(当打不开时会弹框)。
> attachment;filename=xxx:表示类型为附件,并在弹框的界面中显示下载的文件名。
* 流:要下载的文件数据。
> 自己new 一个输入流即可,然后通过IOUtils完成流的数据写入。
2、Struts中的文件下载
通过<result type="stream">来完成。
指定stream结果类型 需要指定一个 inputName参数,该参数指定一个输入流,提供被下载文件的入口。
在struts-default.xml文件中可以找到stream结果视图:
<result-type name="stream" class="org.apache.struts2.dispatcher.StreamResult"/>
在StreamResult类中有三个属性:
* protected String contentType = "text/plain"; // 该属性用于设置下载文件的MIME类型
* protected String contentDisposition = "inline"; // 该属性用于设置进行下载操作以及下载文件的名称
* protected InputStream inputStream; // 该属性用于读取要下载的文件
其中contentType、contentDisposition、inputStream可以在struts.xml文件中进行配置:
<action name="download" class="com.wyc.action.DownloadAction">
<result type="stream">
<param name="contentType">text/plain</param>
<param name="contentDisposition">attachment;filename=a.txt</param>
<!-- ${inputStream}表示调用当前Action的getInputStream()方法,是ognl表达式,如果不设置,则默认"inputStream",可查看StreamResult源码 -->
<param name="inputStream">${inputStream}</param>
</result>
</action>
inputStream可以在Action获得,在Action类中定义一个方法:
public InputStream getInputStream() throw FileNotFound {
FileInputStream fis = new FileInputStream("F;/upload/" + filename);
return fis;
}
然后直接在execute()方法中return SUCCESS即可。
3、文件乱码问题
超链接下载的文件是中文名,会出现乱码情况,服务器会出错。
解决方法:
在getInputStream()方法中添加:
filename = new String(filename.getBytes("iso-8859-1"), "utf-8");
4、动态获取下载文件名和文件类型
在struts.xml文件中使用ognl表达式动态获取。
<result type="stream">
<!-- 调用当前Action中的getContentType()方法,得到其返回值 -->
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename=${downloadFileName}</param>
<!-- ${inputStream}表示调用当前Action的getInputStream()方法,如果不设置,则默认"inputStream",可查看StreamResult源码 -->
<param name="inputStream"></param>
</result>
5、示例代码:
=============================================================================
DownloadAction:
package com.wyc.action;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Base64;
import org.apache.struts2.ServletActionContext;
import sun.misc.BASE64Encoder;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class DownloadAction extends ActionSupport {
// 要下载文件的名称
private String filename;
public InputStream getInputStream() throws FileNotFoundException, UnsupportedEncodingException{
filename = new String(filename.getBytes("iso-8859-1"), "utf-8");
FileInputStream fis = new FileInputStream("f:/upload/" + filename);
return fis;
}
// 获取下载文件MIME类型
public String getContentType(){
return ServletActionContext.getServletContext().getMimeType(filename);
}
/*
* 获取下载文件名称
* 解决浏览器差异问题
*/
public String getDownloadFileName() throws UnsupportedEncodingException{
String agent = ServletActionContext.getRequest().getHeader("User-Agent");
if(agent.contains("MSIE")){
// IE浏览器
filename = URLEncoder.encode(filename, "utf-8");
} else if (agent.contains("FireFox")) {
// 火狐浏览器
BASE64Encoder base64Encoder = new BASE64Encoder();
filename = "=?utf-8?B?" + base64Encoder.encode(filename.getBytes("utf-8")) + "?=";
} else {
// 其他浏览器
filename = URLEncoder.encode(filename, "utf-8");
}
return filename;
}
@Override
public String execute() throws Exception {
System.out.println("进行下载...");
// 直接return SUCCESS即可。
return SUCCESS;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
}
----------------------------------------------------------------------------------------------------------------------------
struts.xml
<?xml version="1.0" encoding="UTF-8"?>
<struts>
<package name="default" namespace="/" extends="struts-default">
<action name="download" class="com.wyc.action.DownloadAction">
<result type="stream">
<!-- 调用当前Action中的getContentType()方法,得到其返回值 -->
<param name="contentType">${contentType}</param>
<param name="contentDisposition">attachment;filename=${downloadFileName}</param>
<!-- ${inputStream}表示调用当前Action的getInputStream()方法,如果不设置,则默认"inputStream",可查看StreamResult源码 -->
<param name="inputStream"></param>
</result>
</action>
</package>
</struts>