文件上传是我们在实际开发中经常遇到的一个问题,曾经使用commons-fileupload组件实现过文件上传下载;同样的,Struts2也可以实现文件上传下载,并且操作起来更加简单(以下只是一个简单的Demo,并不包含文件类型、大小判断等问题)。
总结:
文件上传的核心在于action类的编写,注意在Action中定义了几个属性来封装文件信息:
a.File类型的xxx——封装上传的文件,与表单中FIle控件中的name属性值保持一致
b.String类型的xxxFileName——封装文件的名称(含后缀名),xxx就是表单中File控件的name属性值,FileName是固定写法
c.String类型的xxxContentType——封装文件的类型,xxx同上,ContentType为固定写法
提交表单后框架会自动帮助我们把文件映射到Action类中。
一、文件上传
1.单文件上传
①创建web项目FileUpDownloadDemo,并添加Struts2框架支持,创建upload.jsp,并准备好表单,如下:
<!--
准备好表单,当然我这里使用的是Struts2的标签,也可以使用input等普通标签,注意:
method:当然一定是post方式
enctyppe:使用的是 multipart/form-data方式
-->
<s:form action="upload" method="post" enctype="multipart/form-data">
<s:textfield name="title" label="请选择文件"/>
<s:file name="file" label="选择文件"/>
<s:submit value="上传"/>
</s:form>
②编写创建FileUploadAction类,继承ActionSupport
package com.wzj.action;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.struts2.ServletActionContext;
import com.opensymphony.xwork2.ActionSupport;
public class FileUploadAction extends ActionSupport {
//定义一个File类型的属性,属性名称和表单元素中file标签的name属性值一致
private File file;
//定义一个String型的xxxContentType,固定写法,前缀是上面属性的名字
private String fileContentType;
//定义一个String的xxxFileName,固定写法,前缀同上
private String fileFileName;
//此属性和struts.xml文件action中的param元素对应
private String savePath;
/**
* 处理上传文件请求
* @return
*/
public String upload(){
FileInputStream fis=null;
FileOutputStream fos=null;
try {
//为file属性提供好get、set方法后Struts2会自动将文件映射 到file属性值中,
fis=new FileInputStream(getFile());
fos=new FileOutputStream(getSavePath()+"\\"+getFileFileName());
//创建缓冲区
byte[] buf=new byte[fis.available()];
//读写文件
fis.read(buf);
fos.write(buf);
fos.flush();
return SUCCESS;
} catch (FileNotFoundException e) {
e.printStackTrace();
return ERROR;
} catch (IOException e) {
e.printStackTrace();
return ERROR;
}finally{
try {
fis.close();
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String getSavePath() {
//对路径做了下封装,表示服务器本地磁盘的实际保存位置
return ServletActionContext.getServletContext().getRealPath(savePath);
}
//省略其他get、set方法
}
③在struts.xml文件中配置action
<action name="upload" class="com.wzj.action.FileUploadAction" method="upload">
<!--
注意此处使用param元素向action类中传递参数,即FileUploadAction类中的
savePath属性,注意:name值要和属性名字保持一致!
-->
<param name="savePath">/uploadFiles</param>
<result name="success">/success.jsp</result>
<result name="error">/error.jsp</result>
</action>
④运行项目,选择文件上传后,文件便出现在Tomcat目录下项目的uploadFiles目录下。
总结:
文件上传的核心在于action类的编写,注意在Action中定义了几个属性来封装文件信息:
a.File类型的xxx——封装上传的文件,与表单中FIle控件中的name属性值保持一致
b.String类型的xxxFileName——封装文件的名称(含后缀名),xxx就是表单中File控件的name属性值,FileName是固定写法
c.String类型的xxxContentType——封装文件的类型,xxx同上,ContentType为固定写法
提交表单后框架会自动帮助我们把文件映射到Action类中。
2.多文件上传
多文件上传的基本步骤同单文件上传的步骤类似,只不过将Action类中的属性定义为数组的形式,即如:private File[] file;
private String[] fileFileName;
private String[] fileContentType;
//....
当然也可以使用在表单中声明多个控件的方式,但是这种方式会造成Action类中的属性冗余,不建议使用。
二、文件下载
相对于文件上传来说,文件下载更为简单,Struts2通过stream结果类型来实现下载功能,在Action类中只需要指定一个获得inputStream输入流的方法,通过这个输入流就可以向外输出文件内容。当然,还得需要对相关参数进行配置。stream结果类型有以下几个参数:
名称 | 作用 |
---|---|
contentType | 设置发送到浏览器的MIME类型 |
contentLength | 设置文件的大小 |
contentDisposition | 设置响应的头信息中的Content-Disposition参数的值 |
inputName | 指定Action中提供的inputStream类型的属性名称 |
bufferSizes | 设置读取和下载文件时缓冲区的大小 |
contentType的类型有:
文件类型 | contentType设置 |
---|---|
Word | application/msword |
Excel | Application/vnd.ms-excel |
PPT | Application/vnd.ms-powerpoint |
图片 | image/gif、image/bmp、image/jpeg |
文本文件 | text/plain |
HTML网页 | text/html |
可执行文件 | application/octet-stream |
①创建download.jsp,并简单书写一个超链接
<a href="download?name=test.png">点击我下载测试文件</a>
②创建FileDownloadAction类:
package com.wzj.action;
import java.io.BufferedInputStream;
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 {
//下载文件中的名称,从url参数中获取
private String name;
//下载文件保存在服务器端的路径
private String inputPath;
//下载文件的类型
private String contentType;
//读取下载文件的输入流
private InputStream inputStream;
public String execute(){
return SUCCESS;
}
public InputStream getInputStream() throws FileNotFoundException {
String path=ServletActionContext.getServletContext().getRealPath(inputPath);
return new BufferedInputStream(new FileInputStream(path+"\\"+name));
}
//省略其他get、set方法
}
③对action进行配置:
<action name="download" class="com.wzj.action.FileDownloadAction">
<param name="inputPath">/uploadFiles</param>
<result name="success" type="stream">
/success.jsp
<!-- 注意需要配置以下参数 -->
<param name="contentType">application/octet-stream</param>
<param name="inputName">inputStream</param>
<param name="contentDisposition">attachment;filename="${name}"</param>
<param name="bufferSize">4096</param>
</result>
</action>
④运行,点击链接,将会出现下面的窗口