文件上传
struts 2 并不能自己对二进制流的文件数据去请求,它还是需要哦借助于其他的上传框架去处理,它只是在这些上传的框架基础上进行了封装。
我们解压struts 的核心jar包,找到下面这个文件:default.properties
Struts 2框架有两个核心配置文件,其中struts.xml文件主要负责管理应用中的Action映射,以及该Action包含的Result定义等。除此之外,Struts 2框架还包含struts.properties文件,该文件定义了Struts 2框架的大量属性,开发者可以通过改变这些属性来满足应用的需求。
大家可以自己看看,其中有关于文件上传的配置上传的框架。
Struts 为我们提供了这3中上传文件的框架,jakarta是默认的(采用默认的是不需要重写Struts.properties),如果要换这3种种的其他一种,我们需要重新写一个Struts.properties。存放到src,这样编译之后,文件会在web-inf/classes下,这样Struts就不会加载默认的原先它自己文件,而是加载你自己指定的,这点和Strut.xml很类似,以及模板文件。
指定了上传文件的框架,还需要导入相应的jar包。
完成上面准备工作,下面我们就要开始进行文件的上传了。
<s:form action="upload" method="post" enctype="multipart/form-data">
<s:textfield name="filetitle" label="文件标题"/>
<s:file label="文件选择" name="upload" /><!--该控件用于生成文件的上传域 -->
<s:submit value="上传"/>
</s:form>
注意:上传文件的form必须要有
method="post" enctype="multipart/form-data">
private String filetitle;//这个是文件title
private File upload;//封装的文件内容
private String uploadContentType;//这个属性是封住文件的类型
private String uploadFileName;//这个属性是封装文件的名字
//上面这三个封装属性是规定死的,你用struts,就必须这样写
private String savePath;//这个属性可以设置文件存放的位置,它的值是可以动态设置的,在配置文件上传的action中。此外,你还需要在web工程创建你设置的对应的文件夹。
public String getSavePath() {
return ServletActionContext.getServletContext().getRealPath("/WEB-INF"+savePath);
}
public void setSavePath(String savePath) {
this.savePath = savePath;
}
public String getFiletitle() {
return filetitle;
}
public void setFiletitle(String filetitle) {
this.filetitle = filetitle;
}
public File getUpload() {
return upload;
}
public void setUpload(File upload) {
this.upload = upload;
}
public String getUploadContentType() {
return uploadContentType;
}
public void setUploadContentType(String uploadContentType) {
this.uploadContentType = uploadContentType;
}
public String getUploadFileName() {
return uploadFileName;
}
public void setUploadFileName(String uploadFileName) {
this.uploadFileName = uploadFileName;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
System.out.println(upload.getName());
//upload_296043e8_a58d_4e59_8565_3bfdf68a1f2f_00000001.tmp
FileOutputStream fos = new FileOutputStream(getSavePath()+"\\"+getUploadFileName());
FileInputStream fis = new FileInputStream(getUpload());
byte[] buffer = new byte[1024];
int len =0;
while((len=fis.read(buffer))!=-1){//读1024个字节,返回是真正读到的个数
fos.write(buffer,0,len);//将每次读到的保存到数组中,然后一次写进去
}
return SUCCESS;
}
文件上传的action配置
<action name="upload" class="com.example.test.action.UploadAction" >
<result name="success">/show.jsp</result>
<param name="savePath">/uploadFiles</param>//动态设置action的savePath属性值。
</action>
//显示上传的图片
<img src="./uploadFiles/logo.jpg"/>
<img src="<s:property value="'uploadFiles/'+uploadFileName"/>"/>
注意上传的文件在tomcat的服务端才有,不是你上传之后,工程下就有对应的文件的。
手动实现文件的过滤
web是不允许用户任意上传应用的,特别是可执行文件,可能会含有病毒。
我们可以在action的校验方法中,实现对文件的过滤。
对文件类型、大小的过滤
在前面的代码的基础上,添加如下内容:
private String allowTypes;//并且提供对应的set、get方法
public String checkFile(){
String[] types = getAllowTypes().split(",");
for(String type:types){
if(type.equals(uploadContentType)&&upload.length()<2000){
return null;
}
}
return ERROR;
}
@Override
public void validate() {
// TODO Auto-generated method stub
if(checkFile()!=null){
addFieldError("error", "文件上传类型有误");
}
}
<result name="input">/error.jsp</result>//配置错误的视图
<param name="allowTypes">image/png,image/jpeg</param>//这个name你可以随便定义,只要与action中的一致就好,允许的类型值,可以参考httpcontenttype的
对文件大小限制,主要就是同upload是对文件封装,可以通过length去获取文件的大小,大小是以字节B为单位的。
使用拦截器实现文件的过滤
我们在原来的代码基础上,注释校验那个方法,在struts的配置文件中,做如下添加:
<interceptor-ref name="fileUpload">
<param name="allowTypes">image/png,image/jpeg</param>
<param name="maximumSize">2000</param>
</interceptor-ref>
<interceptor-ref name="defaultStack"/>
便可轻松实现文件类型、大小的过滤。
注意:这里的两个参数的name是不可以修改,是struts规定好的。
文件输出错误提示
编写国际资源文件,存放在src下,同时在struts.xml配置一下。
struts.messages.error.content.type.not.allowed=\u6587\u4EF6\u7C7B\u578B\u4E0D\u5141\u8BB8
struts.messages.error.file.too.large=\u4E0A\u4F20\u6587\u4EF6\u592A\u5927
第一个常量是文件类型不匹配
第二个常量是文件大小不匹配
struts.messages.error.uploading 该常量是文件上传未知的错,既不是文件类型不允许,也不是文件大小。
是先检查文件大小是否合格。
文件上传常量配置
<constant name="struts.multipart.saveDir" value="d:"/> struts 上传文件是使用指定的临时文件夹
<constant name="struts.multipart.maxSize" value="20"/> 指定上传表单最大字节数
struts 文件下载
你可以使用超链接去下载文件,也可以通过表单。
定义action
public class DownAction extends ActionSupport {
//该参数是用定义服务器资源的路径
//在这是通过依赖注入的方式,在struts.xml动态设置
private String inputPath;
public void setInputPath(String inputPath) {
this.inputPath = inputPath;
}
//定义一个返回inputstream 方法
//该方法是作为下载文件的入口
//inputName 的配置的值,就是该方法的名字,去除get,首字母小写
public InputStream getTargetFile() throws Exception{
InputStream in = ServletActionContext.getServletContext().getResourceAsStream(inputPath);
return in;
}
@Override
public String execute() throws Exception {
// TODO Auto-generated method stub
InputStream in = getTargetFile();
OutputStream out = new FileOutputStream(new File("d:\\test.jpg"));
int size = 0;
byte[] buffer = new byte[1024];
while((size=in.read(buffer))!=-1){
out.write(buffer, 0, size);
}
out.flush();
out.close();
return super.execute();
}
}
注意:虽然获取流的那个方法不是重写,是你自己定义getXxxxx,尽量还是取名字右意义的。
<action name="down" class="com.example.test.action.DownAction">
<param name="inputPath">WEB-INF/image/woman1.jpg</param>//注意action下的参数,应该在action下面
<result name="success" type="stream">//注意返回的结果集是一个流,并不是真正的视图
//这边的参数是result结果集的参数
<param name="contentType">image/jpg</param>//下载的文件类型,和互联网标准的mime一致
<param name="inputName">targetFile</param>//对应获取流的方法
<param name="contentDisposition">attachment;filename="womanlaoqiang.jpg"</param>
<param name="bufferSize">2048</param>//文件缓冲区大小
</result>
</action>
contentDisposition 是用来进行文件下载处理方式,以及下载文件的名字。
处理方式包括内联(inline)和附件(attachment)两种方式,而附件方式会弹出文件保存对话框,否则浏览器会尝试直接显示文件,默认是内联,会强行打开。
界面
<s:form method="post" action="down">
<s:submit value="下载"/>
</s:form>
//表单、超链接下载均可以
<a href="down">下载</a>